Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/07/14 16:55:50 (10 years ago)
Author:
gkronber
Message:

#2076,#2159, #2092
multi-ticket merge to stable:

Location:
stable
Files:
2 deleted
14 edited
4 copied

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views

  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs

    r10520 r11120  
    2222using System;
    2323using System.Collections.Generic;
     24using System.Drawing;
    2425using System.Globalization;
    2526using System.Linq;
     
    3637      {"StartSymbol","RPB"}
    3738    };
    38     private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>();
     39
     40    private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine;
    3941
    4042    public SymbolicExpressionTreeLatexFormatter()
    4143      : base("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.") {
    42       layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> {
     44      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
    4345        HorizontalSpacing = 2,
    4446        VerticalSpacing = 2,
     
    5759
    5860    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
    59       layoutEngine.Reset();
    6061      var root = symbolicExpressionTree.Root;
    6162      var actualRoot = root.SubtreeCount == 0 ? root.GetSubtree(0) : root;
    62       layoutEngine.Initialize(actualRoot, x => x.Subtrees);
    63       layoutEngine.CalculateLayout();
    64       var nodeCoordinates = layoutEngine.GetCoordinates();
     63      var nodeCoordinates = layoutEngine.CalculateLayout(actualRoot).ToDictionary(n => n.Content, n => new PointF(n.X, n.Y));
    6564      var sb = new StringBuilder();
    6665      var nl = Environment.NewLine;
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/GraphicalSymbolicExpressionTreeView.Designer.cs

    r9456 r11120  
    1919 */
    2020#endregion
     21
     22using System.Drawing;
    2123
    2224namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
     
    5961      this.symbolicExpressionTreeChart.Spacing = 5;
    6062      this.symbolicExpressionTreeChart.TabIndex = 0;
    61       this.symbolicExpressionTreeChart.TextFont = new System.Drawing.Font("Times New Roman", 6F);
     63      this.symbolicExpressionTreeChart.TextFont = new System.Drawing.Font(FontFamily.GenericSerif, 8F);
    6264      //
    6365      // FunctionTreeView
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views-3.4.csproj

    r8600 r11120  
    110110  </ItemGroup>
    111111  <ItemGroup>
     112    <Compile Include="Formatters\SymbolicExpressionTreeLatexFormatter.cs" />
     113    <Compile Include="LayoutEngines\BoxesLayoutEngine.cs" />
     114    <Compile Include="LayoutEngines\ILayoutEngine.cs" />
     115    <Compile Include="LayoutEngines\LayoutNode.cs" />
     116    <Compile Include="LayoutEngines\ReingoldTilfordLayoutEngine.cs" />
    112117    <Compile Include="Plugin.cs" />
    113118    <Compile Include="SymbolicExpressionGrammarAllowedChildSymbolsControl.cs">
     
    160165      <DependentUpon>SymbolicExpressionView.cs</DependentUpon>
    161166    </Compile>
    162     <Compile Include="VisualSymbolicExpressionTreeNode.cs" />
    163     <Compile Include="VisualSymbolicExpressionTreeNodeConnection.cs" />
     167    <Compile Include="VisualTreeNode.cs" />
     168    <Compile Include="VisualTreeNodeConnection.cs" />
    164169  </ItemGroup>
    165170  <ItemGroup>
     
    276281  -->
    277282  <PropertyGroup>
    278    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
     283    <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)
    279284set ProjectDir=$(ProjectDir)
    280285set SolutionDir=$(SolutionDir)
     
    283288call PreBuildEvent.cmd
    284289</PreBuildEvent>
    285 <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
     290    <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
    286291export ProjectDir=$(ProjectDir)
    287292export SolutionDir=$(SolutionDir)
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/BoxesLayoutEngine.cs

    r10520 r11120  
    1 
     1#region License Information
     2
     3/* HeuristicLab
     4 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     5 *
     6 * This file is part of HeuristicLab.
     7 *
     8 * HeuristicLab is free software: you can redistribute it and/or modify
     9 * it under the terms of the GNU General Public License as published by
     10 * the Free Software Foundation, either version 3 of the License, or
     11 * (at your option) any later version.
     12 *
     13 * HeuristicLab is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 * GNU General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU General Public License
     19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     20 */
     21
     22#endregion
     23
    224using System;
    325using System.Collections.Generic;
    4 using System.Drawing;
    526using System.Linq;
    627
    728namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
    829  public class BoxesLayoutEngine<T> : ILayoutEngine<T> where T : class {
    9     private readonly Dictionary<T, VisualTreeNode<T>> nodeMap;
    10 
    1130    public int NodeWidth { get; set; }
    1231    public int NodeHeight { get; set; }
    1332    public int HorizontalSpacing { get; set; }
    1433    public int VerticalSpacing { get; set; }
    15     private VisualTreeNode<T> layoutRoot;
    1634
    17     public int Width { get; private set; }
    18     public int Height { get; private set; }
     35    private readonly Func<T, IEnumerable<T>> GetChildren;
     36    private readonly Func<T, int> GetLength;
     37    private readonly Func<T, int> GetDepth;
    1938
    20     public Func<T, IEnumerable<T>> GetChildren { get; set; }
    21     public Func<T, int> GetLength { get; set; }
    22     public Func<T, int> GetDepth { get; set; }
     39    public BoxesLayoutEngine(Func<T, IEnumerable<T>> GetChildren, Func<T, int> GetLength, Func<T, int> GetDepth) {
     40      if (GetChildren == null) throw new ArgumentNullException("GetChildren");
     41      if (GetLength == null) throw new ArgumentNullException("GetLength");
     42      if (GetDepth == null) throw new ArgumentNullException("GetDepth");
    2343
    24     public BoxesLayoutEngine() {
    25       nodeMap = new Dictionary<T, VisualTreeNode<T>>();
     44      this.GetChildren = GetChildren;
     45      this.GetLength = GetLength;
     46      this.GetDepth = GetDepth;
    2647    }
    2748
    28     public void CalculateLayout() {
    29       throw new Exception("The BoxesLayoutEngine does not support arbitrary bounds. Please use method CalculateLayout(Width, Height)");
     49
     50    public IEnumerable<VisualTreeNode<T>> CalculateLayout(T root, float width, float height) {
     51      var nodeMap = new Dictionary<T, VisualTreeNode<T>>();
     52      CreateVisualNodes(root, nodeMap);
     53      RecursiveLayout(nodeMap, nodeMap[root], 0, 0, (int)Math.Round(width), (int)Math.Round(height) / GetDepth(root));
     54      return nodeMap.Values;
    3055    }
    3156
    32     public void CalculateLayout(float width, float height) {
    33       Width = (int)Math.Round(width);
    34       Height = (int)Math.Round(height);
    35       Reset();
    36       RecursiveLayout(layoutRoot, 0, 0, Width, Height / GetDepth(layoutRoot.Content));
    37     }
    38 
    39     public void Initialize(T root, Func<T, IEnumerable<T>> getChildren, Func<T, int> getLength, Func<T, int> getDepth) {
    40       if (getChildren == null || getLength == null || getDepth == null)
    41         throw new ArgumentNullException("The BoxesLayoutEngine requires all of the lambdas: (getChildren, getLength and getDepth) to be defined.");
    42       GetChildren = getChildren;
    43       GetLength = getLength;
    44       GetDepth = getDepth;
    45       Clear();
    46       Expand(root); // produce the nodeMap
    47       layoutRoot = nodeMap[root];
    48     }
    49 
    50     private void Expand(T root) {
     57    private void CreateVisualNodes(T root, Dictionary<T, VisualTreeNode<T>> map) {
    5158      var node = new VisualTreeNode<T>(root) {
    5259        PreferredWidth = NodeWidth,
    5360        PreferredHeight = NodeHeight
    5461      };
    55       nodeMap.Add(root, node);
     62
     63      map.Add(root, node);
    5664      var children = GetChildren(root).ToList();
    5765      if (children.Any()) {
    5866        foreach (var child in children) {
    59           Expand(child);
     67          CreateVisualNodes(child, map);
    6068        }
    6169      }
    6270    }
    6371
    64     public void Center(float width, float height) {
    65       // does nothing because the BoxesLayout centers the tree by default
    66     }
    67 
    68     public void Clear() {
    69       nodeMap.Clear();
    70       layoutRoot = null;
    71     }
    72 
    73     public void Reset() {
    74       foreach (var node in nodeMap.Values) {
    75         node.X = 0;
    76         node.Y = 0;
    77       }
    78     }
    79 
    80     public Dictionary<T, PointF> GetCoordinates() {
    81       return nodeMap.ToDictionary(x => x.Key, x => new PointF(x.Value.X, x.Value.Y));
    82     }
    83 
    84     public void FitToBounds(float width, float height) {
    85       // does nothing because the BoxesLayout is by default stretched on the whole drawing area
    86     }
    87 
    88     private void RecursiveLayout(VisualTreeNode<T> visualTreeNode, int x, int y, int width, int height) {
     72    private void RecursiveLayout(Dictionary<T, VisualTreeNode<T>> nodeMap, VisualTreeNode<T> visualTreeNode, int x, int y, int width, int height) {
    8973      float center_x = x + width / 2;
    9074      float center_y = y + height / 2;
    91       int actualWidth = width - VerticalSpacing;
     75      int actualWidth = width - HorizontalSpacing;
    9276      int actualHeight = height - VerticalSpacing;
    9377
     
    120104        visualTreeNode.Y = y;
    121105      }
    122       //calculate areas for the subtrees according to their tree size and call drawFunctionTree
     106      //calculate areas for the subtrees according to their tree size
    123107      var node = visualTreeNode.Content;
    124108      var children = GetChildren(node).ToList();
     
    127111      for (int i = 0; i < children.Count; i++) {
    128112        xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)GetLength(children[i])) / (GetLength(node) - 1));
    129         RecursiveLayout(nodeMap[children[i]], xBoundaries[i], y + height, xBoundaries[i + 1] - xBoundaries[i], height);
     113        RecursiveLayout(nodeMap, nodeMap[children[i]], xBoundaries[i], y + height, xBoundaries[i + 1] - xBoundaries[i], height);
    130114      }
    131     }
    132 
    133     public IEnumerable<VisualTreeNode<T>> GetVisualNodes() {
    134       return nodeMap.Values;
    135115    }
    136116  }
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ILayoutEngine.cs

    r10520 r11120  
    1 
    2 using System;
     1#region License Information
     2
     3/* HeuristicLab
     4 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     5 *
     6 * This file is part of HeuristicLab.
     7 *
     8 * HeuristicLab is free software: you can redistribute it and/or modify
     9 * it under the terms of the GNU General Public License as published by
     10 * the Free Software Foundation, either version 3 of the License, or
     11 * (at your option) any later version.
     12 *
     13 * HeuristicLab is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 * GNU General Public License for more details.
     17 *
     18 * You should have received a copy of the GNU General Public License
     19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
     20 */
     21
     22#endregion
     23
    324using System.Collections.Generic;
    4 using System.Drawing;
    525
    626namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
     
    1131    int VerticalSpacing { get; set; }
    1232
    13     void CalculateLayout();
    14     void CalculateLayout(float width, float height);
    15     void Initialize(T root, Func<T, IEnumerable<T>> getChildren, Func<T, int> getLength = null, Func<T, int> getDepth = null);
    16     void Clear();
    17     void Reset();
    18 
    19     // function members necessary to navigate the tree structure
    20     Func<T, IEnumerable<T>> GetChildren { get; set; }
    21     Func<T, int> GetLength { get; set; }
    22     Func<T, int> GetDepth { get; set; }
    23 
    24     IEnumerable<VisualTreeNode<T>> GetVisualNodes();
    25     Dictionary<T, PointF> GetCoordinates();
     33    IEnumerable<VisualTreeNode<T>> CalculateLayout(T root, float width, float height);
    2634  }
    2735}
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/LayoutNode.cs

    r10520 r11120  
    2525
    2626namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
    27   public class LayoutNode<T> : object where T : class {
     27  internal class LayoutNode<T> : object where T : class {
    2828    public float Width { get; set; }
    2929    public float Height { get; set; }
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ReingoldTilfordLayoutEngine.cs

    r10520 r11120  
    77namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
    88  public class ReingoldTilfordLayoutEngine<T> : ILayoutEngine<T> where T : class {
    9     private readonly Dictionary<T, LayoutNode<T>> nodeMap; // provides a reverse mapping T => LayoutNode
    109    public int NodeWidth { get; set; }
    1110    public int NodeHeight { get; set; }
     
    2221    }
    2322
    24     public Func<T, IEnumerable<T>> GetChildren { get; set; }
    25     public Func<T, int> GetLength { get; set; }
    26     public Func<T, int> GetDepth { get; set; }
    27     private LayoutNode<T> layoutRoot;
    28 
    29     public ReingoldTilfordLayoutEngine() {
    30       nodeMap = new Dictionary<T, LayoutNode<T>>();
    31     }
    32 
    33     public ReingoldTilfordLayoutEngine(T root, Func<T, IEnumerable<T>> childrenFunc)
    34       : this() {
    35       Initialize(root, childrenFunc);
    36     }
    37 
    38     public void Initialize(T root, Func<T, IEnumerable<T>> getChildren, Func<T, int> getLength = null, Func<T, int> getDepth = null) {
    39       GetChildren = getChildren;
    40       Clear();
    41       var node = new LayoutNode<T> { Content = root, Width = NodeWidth, Height = NodeHeight };
    42       node.Ancestor = node;
    43       layoutRoot = node;
    44       Expand(node);
    45     }
    46 
    47     private void Expand(LayoutNode<T> lRoot) {
    48       nodeMap.Add(lRoot.Content, lRoot);
     23    private readonly Func<T, IEnumerable<T>> GetChildren;
     24
     25    public ReingoldTilfordLayoutEngine(Func<T, IEnumerable<T>> GetChildren) {
     26      this.GetChildren = GetChildren;
     27    }
     28
     29    public IEnumerable<VisualTreeNode<T>> CalculateLayout(T root) {
     30      return CalculateLayout(root, 0, 0);
     31    }
     32
     33    public IEnumerable<VisualTreeNode<T>> CalculateLayout(T root, float width, float height) {
     34      Dictionary<T, LayoutNode<T>> layoutNodeMap = new Dictionary<T, LayoutNode<T>>();
     35      var layoutRoot = new LayoutNode<T> { Content = root, Width = NodeWidth, Height = NodeHeight, };
     36      layoutRoot.Ancestor = layoutRoot;
     37      Expand(layoutRoot, layoutNodeMap);
     38
     39      FirstWalk(layoutRoot);
     40      SecondWalk(layoutRoot, -layoutRoot.Prelim);
     41      NormalizeCoordinates(layoutNodeMap.Values);
     42      if (height != 0 && width != 0) {
     43        FitToBounds(width, height, layoutNodeMap.Values);
     44        Center(width, height, layoutNodeMap.Values);
     45      }
     46
     47      return layoutNodeMap.Values.Select(x => new VisualTreeNode<T>(x.Content) {
     48        Width = (int)Math.Round(x.Width),
     49        Height = (int)Math.Round(x.Height),
     50        X = (int)Math.Round(x.X),
     51        Y = (int)Math.Round(x.Y)
     52      });
     53    }
     54
     55    private void Expand(LayoutNode<T> lRoot, Dictionary<T, LayoutNode<T>> map) {
     56      map.Add(lRoot.Content, lRoot);
    4957      var children = GetChildren(lRoot.Content).ToList();
    5058      if (!children.Any()) return;
     
    6169        node.Ancestor = node;
    6270        lRoot.Children.Add(node);
    63         Expand(node);
    64       }
    65     }
    66 
    67     public IEnumerable<VisualTreeNode<T>> GetVisualNodes() {
    68       return nodeMap.Values.Select(x => new VisualTreeNode<T>(x.Content) {
    69         Width = (int)Math.Round(x.Width),
    70         Height = (int)Math.Round(x.Height),
    71         X = (int)Math.Round(x.X),
    72         Y = (int)Math.Round(x.Y)
    73       });
    74     }
    75 
    76     public void AddNode(T content) {
    77       if (nodeMap.ContainsKey(content)) { throw new ArgumentException("Content already present in the dictionary."); }
    78       var node = new LayoutNode<T> { Content = content };
    79       nodeMap.Add(content, node);
    80     }
    81 
    82     public void AddNode(LayoutNode<T> node) {
    83       var content = node.Content;
    84       if (nodeMap.ContainsKey(content)) { throw new ArgumentException("Content already present in the dictionary."); }
    85       nodeMap.Add(content, node);
    86     }
    87 
    88     public void AddNodes(IEnumerable<LayoutNode<T>> nodes) {
    89       foreach (var node in nodes)
    90         nodeMap.Add(node.Content, node);
    91     }
    92 
    93     public LayoutNode<T> GetNode(T content) {
    94       LayoutNode<T> layoutNode;
    95       nodeMap.TryGetValue(content, out layoutNode);
    96       return layoutNode;
    97     }
    98 
    99     public void ResetCoordinates() {
    100       foreach (var node in nodeMap.Values) {
    101         node.ResetCoordinates();
    102       }
    103     }
    104 
    105     public Dictionary<T, PointF> GetCoordinates() {
    106       return nodeMap.ToDictionary(x => x.Key, x => new PointF(x.Value.X, x.Value.Y));
    107     }
     71        Expand(node, map);
     72      }
     73    }
     74
    10875
    10976    /// <summary>
    11077    /// Transform LayoutNode coordinates so that all coordinates are positive and start from (0,0)
    11178    /// </summary>
    112     private void NormalizeCoordinates() {
    113       var nodes = nodeMap.Values.ToList();
     79    private static void NormalizeCoordinates(IEnumerable<LayoutNode<T>> nodes) {
    11480      float xmin = 0, ymin = 0;
    11581      foreach (var node in nodes) {
     
    12389    }
    12490
    125     public void Center(float width, float height) {
     91    private void Center(float width, float height, IEnumerable<LayoutNode<T>> nodes) {
    12692      // center layout on screen
    127       var bounds = Bounds();
     93      var bounds = Bounds(nodes);
    12894      float dx = 0, dy = 0;
    12995      if (width > bounds.Width) { dx = (width - bounds.Width) / 2f; }
    13096      if (height > bounds.Height) { dy = (height - bounds.Height) / 2f; }
    131       foreach (var node in nodeMap.Values) { node.Translate(dx, dy); }
    132     }
    133 
    134     public void FitToBounds(float width, float height) {
    135       var bounds = Bounds();
     97      foreach (var node in nodes) { node.Translate(dx, dy); }
     98    }
     99
     100    private void FitToBounds(float width, float height, IEnumerable<LayoutNode<T>> nodes) {
     101      var bounds = Bounds(nodes);
    136102      var myWidth = bounds.Width;
    137103      var myHeight = bounds.Height;
     
    139105      if (myWidth <= width && myHeight <= height) return; // no need to fit since we are within bounds
    140106
    141       var layers = nodeMap.Values.GroupBy(node => node.Level, node => node).ToList();
     107      var layers = nodes.GroupBy(node => node.Level, node => node).ToList();
    142108
    143109      if (myWidth > width) {
     
    150116        float spacing = minHorizontalSpacing * x;
    151117        foreach (var layer in layers) {
    152           var nodes = layer.ToList();
     118          var nodesLayer = layer.ToList();
    153119          float minWidth = float.MaxValue;
    154           for (int i = 0; i < nodes.Count - 1; ++i) { minWidth = Math.Min(minWidth, nodes[i + 1].X - nodes[i].X); }
     120          for (int i = 0; i < nodesLayer.Count - 1; ++i) { minWidth = Math.Min(minWidth, nodesLayer[i + 1].X - nodesLayer[i].X); }
    155121          float w = Math.Min(NodeWidth, minWidth - spacing);
    156           foreach (var node in nodes) {
     122          foreach (var node in nodesLayer) {
    157123            node.X += (node.Width - w) / 2f;
    158124            node.Width = w;
     
    178144    }
    179145
    180     public void Clear() {
    181       layoutRoot = null;
    182       nodeMap.Clear();
    183     }
    184 
    185     public void Reset() {
    186       foreach (var layoutNode in nodeMap.Values) {
    187         // reset layout-related parameters
    188         layoutNode.Reset();
    189       }
    190     }
    191 
    192     public void CalculateLayout() {
    193       if (layoutRoot == null) throw new Exception("Layout layoutRoot cannot be null.");
    194       Reset(); // reset node parameters like Mod, Shift etc. and set coordinates to 0
    195       FirstWalk(layoutRoot);
    196       SecondWalk(layoutRoot, -layoutRoot.Prelim);
    197       NormalizeCoordinates();
    198     }
    199 
    200     public void CalculateLayout(float width, float height) {
    201       CalculateLayout();
    202       FitToBounds(width, height);
    203       Center(width, height);
    204     }
    205146
    206147    /// <summary>
     
    208149    /// </summary>
    209150    /// <returns></returns>
    210     public RectangleF Bounds() {
     151    private RectangleF Bounds(IEnumerable<LayoutNode<T>> nodes) {
    211152      float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
    212       var list = nodeMap.Values.ToList();
    213       foreach (LayoutNode<T> node in list) {
     153      foreach (LayoutNode<T> node in nodes) {
    214154        float x = node.X, y = node.Y;
    215155        if (xmin > x) xmin = x;
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarAllowedChildSymbolsControl.cs

    r9456 r11120  
    2929using HeuristicLab.PluginInfrastructure;
    3030
     31using VisualSymbolicExpressionTreeNode = HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.VisualTreeNode<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>;
     32
    3133namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
    3234  public sealed partial class SymbolicExpressionGrammarAllowedChildSymbolsControl : UserControl {
     
    103105
    104106      var tree = new SymbolicExpressionTree(new SymbolicExpressionTreeNode(Symbol));
    105       symbolicExpressionTreeChart.SuspendRepaint = true;
    106107      if (Grammar.GetMaximumSubtreeCount(Symbol) > 0) {
    107108        for (int i = 0; i < Grammar.GetMaximumSubtreeCount(Symbol); i++) {
     
    116117      }
    117118      symbolicExpressionTreeChart.Tree = tree;
    118 
     119      symbolicExpressionTreeChart.SuspendRepaint = true;
    119120      foreach (var subtreeNode in tree.Root.Subtrees) {
    120121        foreach (var allowedChildNode in subtreeNode.Subtrees) {
     
    142143        }
    143144      }
    144 
    145145      symbolicExpressionTreeChart.SuspendRepaint = false;
    146146      UpdateSelectedSymbolicExpressionTreeNodes();
     
    153153        else visualNode.FillColor = Color.LightSteelBlue;
    154154      }
    155       symbolicExpressionTreeChart.Repaint();
     155      symbolicExpressionTreeChart.RepaintNodes();
    156156    }
    157157
     
    162162
    163163      VisualSymbolicExpressionTreeNode clickedNode = (VisualSymbolicExpressionTreeNode)sender;
    164       var selectedNode = clickedNode.SymbolicExpressionTreeNode;
     164      var selectedNode = clickedNode.Content;
    165165      if (selectedNode.SubtreeCount == 0) {
    166166        if (!selectedSymbolicExpressionTreeNodes.Contains(selectedNode))
     
    207207        var visualNode = symbolicExpressionTreeChart.FindVisualSymbolicExpressionTreeNodeAt(coordinates.X, coordinates.Y);
    208208        if (visualNode != null) {
    209           var node = visualNode.SymbolicExpressionTreeNode;
     209          var node = visualNode.Content;
    210210          var root = symbolicExpressionTreeChart.Tree.Root;
    211211          if (node == root || node.Parent == root) e.Effect = DragDropEffects.Copy;
     
    223223      var symbols = data as IEnumerable<ISymbol>;
    224224
    225       if (node.SymbolicExpressionTreeNode == root) {
     225      if (node.Content == root) {
    226226        if (symbol != null)
    227227          Grammar.AddAllowedChildSymbol(root.Symbol, symbol);
     
    229229          foreach (var s in symbols) Grammar.AddAllowedChildSymbol(root.Symbol, s);
    230230      } else {
    231         int argumentIndex = root.IndexOfSubtree(node.SymbolicExpressionTreeNode);
     231        int argumentIndex = root.IndexOfSubtree(node.Content);
    232232        if (symbol != null)
    233233          Grammar.AddAllowedChildSymbol(root.Symbol, symbol, argumentIndex);
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.Designer.cs

    r9456 r11120  
    4949      this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
    5050      this.saveImageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     51      this.exportPgfLaTeXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     52      this.layoutEngineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     53      this.reingoldTilfordToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     54      this.boxesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    5155      this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
    5256      this.contextMenuStrip.SuspendLayout();
     
    5660      //
    5761      this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    58             this.saveImageToolStripMenuItem});
     62            this.saveImageToolStripMenuItem,
     63            this.exportPgfLaTeXToolStripMenuItem,
     64            this.layoutEngineToolStripMenuItem});
    5965      this.contextMenuStrip.Name = "contextMenuStrip";
    60       this.contextMenuStrip.Size = new System.Drawing.Size(135, 26);
     66      this.contextMenuStrip.Size = new System.Drawing.Size(166, 70);
    6167      //
    6268      // saveImageToolStripMenuItem
    6369      //
    6470      this.saveImageToolStripMenuItem.Name = "saveImageToolStripMenuItem";
    65       this.saveImageToolStripMenuItem.Size = new System.Drawing.Size(134, 22);
     71      this.saveImageToolStripMenuItem.Size = new System.Drawing.Size(165, 22);
    6672      this.saveImageToolStripMenuItem.Text = "Save Image";
    6773      this.saveImageToolStripMenuItem.Click += new System.EventHandler(this.saveImageToolStripMenuItem_Click);
     74      //
     75      // exportPgfLaTeXToolStripMenuItem
     76      //
     77      this.exportPgfLaTeXToolStripMenuItem.Name = "exportPgfLaTeXToolStripMenuItem";
     78      this.exportPgfLaTeXToolStripMenuItem.Size = new System.Drawing.Size(165, 22);
     79      this.exportPgfLaTeXToolStripMenuItem.Text = "Export Pgf/LaTeX";
     80      this.exportPgfLaTeXToolStripMenuItem.Click += new System.EventHandler(this.exportLatexToolStripMenuItem_Click);
     81      //
     82      // layoutEngineToolStripMenuItem
     83      //
     84      this.layoutEngineToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
     85            this.reingoldTilfordToolStripMenuItem,
     86            this.boxesToolStripMenuItem});
     87      this.layoutEngineToolStripMenuItem.Name = "layoutEngineToolStripMenuItem";
     88      this.layoutEngineToolStripMenuItem.Size = new System.Drawing.Size(165, 22);
     89      this.layoutEngineToolStripMenuItem.Text = "Layout Engine:";
     90      //
     91      // reingoldTilfordToolStripMenuItem
     92      //
     93      this.reingoldTilfordToolStripMenuItem.Name = "reingoldTilfordToolStripMenuItem";
     94      this.reingoldTilfordToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
     95      this.reingoldTilfordToolStripMenuItem.Text = "Reingold-Tilford";
     96      this.reingoldTilfordToolStripMenuItem.Click += new System.EventHandler(this.reingoldTilfordToolStripMenuItem_Click);
     97      //
     98      // boxesToolStripMenuItem
     99      //
     100      this.boxesToolStripMenuItem.Name = "boxesToolStripMenuItem";
     101      this.boxesToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
     102      this.boxesToolStripMenuItem.Text = "Boxes";
     103      this.boxesToolStripMenuItem.Click += new System.EventHandler(this.boxesToolStripMenuItem_Click);
    68104      //
    69105      // saveFileDialog
    70106      //
    71107      this.saveFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|EMF (*.emf)|*.emf";
    72       this.saveFileDialog.FilterIndex = 1;
     108      //
    73109      // SymbolicExpressionTreeChart
    74110      //
    75       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    76111      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
    77112      this.ContextMenuStrip = this.contextMenuStrip;
     113      this.DoubleBuffered = true;
    78114      this.Name = "SymbolicExpressionTreeChart";
    79115      this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.SymbolicExpressionTreeChart_MouseClick);
     
    93129    protected System.Windows.Forms.ToolStripMenuItem saveImageToolStripMenuItem;
    94130    protected System.Windows.Forms.SaveFileDialog saveFileDialog;
     131    private System.Windows.Forms.ToolStripMenuItem exportPgfLaTeXToolStripMenuItem;
     132    private System.Windows.Forms.ToolStripMenuItem layoutEngineToolStripMenuItem;
     133    private System.Windows.Forms.ToolStripMenuItem reingoldTilfordToolStripMenuItem;
     134    private System.Windows.Forms.ToolStripMenuItem boxesToolStripMenuItem;
    95135  }
    96136}
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs

    r9931 r11120  
    2424using System.Drawing;
    2525using System.Drawing.Imaging;
     26using System.IO;
     27using System.Linq;
    2628using System.Windows.Forms;
     29
    2730
    2831namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
    2932  public partial class SymbolicExpressionTreeChart : UserControl {
    3033    private Image image;
    31     private StringFormat stringFormat;
    32     private Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes;
    33     private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection> visualLines;
     34    private readonly StringFormat stringFormat;
     35    private Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>> visualTreeNodes;
     36    private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection> visualLines;
     37    private ILayoutEngine<ISymbolicExpressionTreeNode> layoutEngine;
     38
     39    private const int preferredNodeWidth = 70;
     40    private const int preferredNodeHeight = 46;
     41    private int minHorizontalDistance = 30;
     42    private int minVerticalDistance = 30;
    3443
    3544    public SymbolicExpressionTreeChart() {
     
    4049      this.lineColor = Color.Black;
    4150      this.backgroundColor = Color.White;
    42       this.textFont = new Font("Times New Roman", 8);
     51      this.textFont = new Font(FontFamily.GenericSansSerif, 12);
     52
     53      visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>>();
     54      visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>();
     55
     56      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
     57        NodeWidth = preferredNodeWidth,
     58        NodeHeight = preferredNodeHeight,
     59        HorizontalSpacing = minHorizontalDistance,
     60        VerticalSpacing = minVerticalDistance
     61      };
     62      reingoldTilfordToolStripMenuItem.Checked = true;
    4363    }
    4464
     
    4868    }
    4969
     70    #region Public properties
    5071    private int spacing;
    5172    public int Spacing {
     
    89110      set {
    90111        tree = value;
    91         visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();
    92         visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection>();
    93         if (tree != null) {
    94           foreach (ISymbolicExpressionTreeNode node in tree.IterateNodesPrefix()) {
    95             visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node);
    96             if (node.Parent != null) visualLines[Tuple.Create(node.Parent, node)] = new VisualSymbolicExpressionTreeNodeConnection();
    97           }
    98         }
    99112        Repaint();
    100113      }
     
    106119      set { suspendRepaint = value; }
    107120    }
     121    #endregion
    108122
    109123    protected override void OnPaint(PaintEventArgs e) {
     
    115129      if (this.Width <= 1 || this.Height <= 1)
    116130        this.image = new Bitmap(1, 1);
    117       else
     131      else {
    118132        this.image = new Bitmap(Width, Height);
     133      }
    119134      this.Repaint();
     135    }
     136
     137    public event EventHandler Repainted;//expose this event to notify the parent control that the tree was repainted
     138    protected virtual void OnRepaint(object sender, EventArgs e) {
     139      var repainted = Repainted;
     140      if (repainted != null) {
     141        repainted(sender, e);
     142      }
    120143    }
    121144
     
    124147        this.GenerateImage();
    125148        this.Refresh();
     149        OnRepaint(this, EventArgs.Empty);
    126150      }
    127151    }
     
    134158          foreach (var visualNode in visualTreeNodes.Values) {
    135159            DrawTreeNode(graphics, visualNode);
     160            if (visualNode.Content.SubtreeCount > 0) {
     161              foreach (var visualSubtree in visualNode.Content.Subtrees.Select(s => visualTreeNodes[s])) {
     162                DrawLine(graphics, visualNode, visualSubtree);
     163              }
     164            }
    136165          }
    137166        }
     
    140169    }
    141170
    142     public void RepaintNode(VisualSymbolicExpressionTreeNode visualNode) {
     171    public void RepaintNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualNode) {
    143172      if (!suspendRepaint) {
    144173        using (var graphics = Graphics.FromImage(image)) {
     
    157186        graphics.Clear(backgroundColor);
    158187        if (tree != null) {
    159           int height = this.Height / tree.Depth;
    160           DrawFunctionTree(tree, graphics, 0, 0, this.Width, height);
    161         }
    162       }
    163     }
    164 
    165     public VisualSymbolicExpressionTreeNode GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) {
     188          DrawFunctionTree(graphics, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance);
     189        }
     190      }
     191    }
     192
     193    public VisualTreeNode<ISymbolicExpressionTreeNode> GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) {
    166194      if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode))
    167195        return visualTreeNodes[symbolicExpressionTreeNode];
     
    169197    }
    170198
    171     public VisualSymbolicExpressionTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {
     199    public VisualTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {
    172200      if (child.Parent != parent) throw new ArgumentException();
    173201      var key = Tuple.Create(parent, child);
    174       VisualSymbolicExpressionTreeNodeConnection connection = null;
     202      VisualTreeNodeConnection connection = null;
    175203      visualLines.TryGetValue(key, out connection);
    176204      return connection;
     
    186214
    187215    protected virtual void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) {
    188       VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
     216      var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
    189217      if (visualTreeNode != null) {
    190218        OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e);
     
    200228
    201229    protected virtual void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) {
    202       VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
     230      VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
    203231      if (visualTreeNode != null)
    204232        OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e);
     
    212240    }
    213241
    214     private VisualSymbolicExpressionTreeNode draggedSymbolicExpressionTree;
     242    private VisualTreeNode<ISymbolicExpressionTreeNode> draggedSymbolicExpressionTree;
    215243    private MouseButtons dragButtons;
    216244    private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) {
     
    224252
    225253    private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) {
    226       VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
     254      VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
    227255      if (draggedSymbolicExpressionTree != null &&
    228256        draggedSymbolicExpressionTree != visualTreeNode) {
     
    239267    }
    240268
    241     public VisualSymbolicExpressionTreeNode FindVisualSymbolicExpressionTreeNodeAt(int x, int y) {
     269    public VisualTreeNode<ISymbolicExpressionTreeNode> FindVisualSymbolicExpressionTreeNodeAt(int x, int y) {
    242270      foreach (var visualTreeNode in visualTreeNodes.Values) {
    243271        if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width &&
     
    249277    #endregion
    250278
     279    private void CalculateLayout(int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) {
     280      layoutEngine.NodeWidth = preferredWidth;
     281      layoutEngine.NodeHeight = preferredHeight;
     282      layoutEngine.HorizontalSpacing = minHDistance;
     283      layoutEngine.VerticalSpacing = minVDistance;
     284
     285      var actualRoot = tree.Root;
     286      if (actualRoot.Symbol is ProgramRootSymbol && actualRoot.SubtreeCount == 1) {
     287        actualRoot = tree.Root.GetSubtree(0);
     288      }
     289
     290      var visualNodes = layoutEngine.CalculateLayout(actualRoot, Width, Height).ToList();
     291      visualTreeNodes = visualNodes.ToDictionary(x => x.Content, x => x);
     292      visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>();
     293      foreach (var node in visualNodes.Select(n => n.Content)) {
     294        foreach (var subtree in node.Subtrees) {
     295          visualLines.Add(new Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(node, subtree), new VisualTreeNodeConnection());
     296        }
     297      }
     298    }
     299
    251300    #region methods for painting the symbolic expression tree
    252     private void DrawFunctionTree(ISymbolicExpressionTree tree, Graphics graphics, int x, int y, int width, int height) {
    253       DrawFunctionTree(tree.Root, graphics, x, y, width, height, Point.Empty);
    254     }
    255 
    256     /// <summary>
    257     ///
    258     /// </summary>
    259     /// <param name="functionTree"> function tree to draw</param>
    260     /// <param name="graphics">graphics object to draw on</param>
    261     /// <param name="x">x coordinate of drawing area</param>
    262     /// <param name="y">y coordinate of drawing area</param>
    263     /// <param name="width">width of drawing area</param>
    264     /// <param name="height">height of drawing area</param>
    265     private void DrawFunctionTree(ISymbolicExpressionTreeNode node, Graphics graphics, int x, int y, int width, int height, Point connectionPoint) {
    266       VisualSymbolicExpressionTreeNode visualTreeNode = visualTreeNodes[node];
    267       float center_x = x + width / 2;
    268       float center_y = y + height / 2;
    269       int actualWidth = width - spacing;
    270       int actualHeight = height - spacing;
    271 
    272       using (var textBrush = new SolidBrush(visualTreeNode.TextColor))
    273       using (var nodeLinePen = new Pen(visualTreeNode.LineColor))
    274       using (var nodeFillBrush = new SolidBrush(visualTreeNode.FillColor)) {
    275 
    276         //calculate size of node
    277         if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
    278           visualTreeNode.Width = visualTreeNode.PreferredWidth;
    279           visualTreeNode.Height = visualTreeNode.PreferredHeight;
    280           visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
    281           visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
    282         }
    283           //width too small to draw in desired sized
    284         else if (actualWidth < visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
    285           visualTreeNode.Width = actualWidth;
    286           visualTreeNode.Height = visualTreeNode.PreferredHeight;
    287           visualTreeNode.X = x;
    288           visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
    289         }
    290           //height too small to draw in desired sized
    291         else if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight < visualTreeNode.PreferredHeight) {
    292           visualTreeNode.Width = visualTreeNode.PreferredWidth;
    293           visualTreeNode.Height = actualHeight;
    294           visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
    295           visualTreeNode.Y = y;
    296         }
    297           //width and height too small to draw in desired size
    298         else {
    299           visualTreeNode.Width = actualWidth;
    300           visualTreeNode.Height = actualHeight;
    301           visualTreeNode.X = x;
    302           visualTreeNode.Y = y;
    303         }
    304 
    305         //draw terminal node
    306         if (node.SubtreeCount == 0) {
    307           graphics.FillRectangle(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
    308           graphics.DrawRectangle(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
    309         } else {
    310           graphics.FillEllipse(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
    311           graphics.DrawEllipse(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
    312         }
    313 
    314         //draw name of symbol
    315         var text = node.ToString();
    316         graphics.DrawString(text, textFont, textBrush, new RectangleF(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height), stringFormat);
    317 
    318         //draw connection line to parent node
    319         if (!connectionPoint.IsEmpty && node.Parent != null) {
    320           var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node.Parent, node);
    321           using (Pen linePen = new Pen(visualLine.LineColor)) {
     301    private void DrawFunctionTree(Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) {
     302      CalculateLayout(preferredWidth, preferredHeight, minHDistance, minVDistance);
     303      var visualNodes = visualTreeNodes.Values;
     304      //draw nodes and connections
     305      foreach (var visualNode in visualNodes) {
     306        DrawTreeNode(graphics, visualNode);
     307        var node = visualNode.Content;
     308        foreach (var subtree in node.Subtrees) {
     309          var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node, subtree);
     310          var visualSubtree = visualTreeNodes[subtree];
     311          var origin = new Point(visualNode.X + visualNode.Width / 2, visualNode.Y + visualNode.Height);
     312          var target = new Point(visualSubtree.X + visualSubtree.Width / 2, visualSubtree.Y);
     313          graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y));
     314          using (var linePen = new Pen(visualLine.LineColor)) {
    322315            linePen.DashStyle = visualLine.DashStyle;
    323             graphics.DrawLine(linePen, connectionPoint, new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y));
     316            graphics.DrawLine(linePen, origin, target);
    324317          }
    325318        }
    326 
    327         //calculate areas for the subtrees according to their tree size and call drawFunctionTree
    328         Point connectFrom = new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y + visualTreeNode.Height);
    329         int[] xBoundaries = new int[node.SubtreeCount + 1];
    330         xBoundaries[0] = x;
    331         for (int i = 0; i < node.SubtreeCount; i++) {
    332           xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)node.GetSubtree(i).GetLength()) / (node.GetLength() - 1));
    333           DrawFunctionTree(node.GetSubtree(i), graphics, xBoundaries[i], y + height, xBoundaries[i + 1] - xBoundaries[i], height, connectFrom);
    334         }
    335       }
    336     }
    337 
    338     protected void DrawTreeNode(VisualSymbolicExpressionTreeNode visualTreeNode) {
    339       using (var graphics = Graphics.FromImage(image)) {
    340         graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
    341         graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
    342         DrawTreeNode(graphics, visualTreeNode);
    343       }
    344     }
    345 
    346     protected void DrawTreeNode(Graphics graphics, VisualSymbolicExpressionTreeNode visualTreeNode) {
     319      }
     320    }
     321
     322    protected void DrawTreeNode(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) {
    347323      graphics.Clip = new Region(new Rectangle(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width + 1, visualTreeNode.Height + 1));
    348324      graphics.Clear(backgroundColor);
    349       var node = visualTreeNode.SymbolicExpressionTreeNode;
     325      var node = visualTreeNode.Content;
    350326      using (var textBrush = new SolidBrush(visualTreeNode.TextColor))
    351327      using (var nodeLinePen = new Pen(visualTreeNode.LineColor))
     
    364340      }
    365341    }
     342
     343    protected void DrawLine(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> startNode, VisualTreeNode<ISymbolicExpressionTreeNode> endNode) {
     344      var origin = new Point(startNode.X + startNode.Width / 2, startNode.Y + startNode.Height);
     345      var target = new Point(endNode.X + endNode.Width / 2, endNode.Y);
     346      graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y));
     347      var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(startNode.Content, endNode.Content);
     348      using (var linePen = new Pen(visualLine.LineColor)) {
     349        linePen.DashStyle = visualLine.DashStyle;
     350        graphics.DrawLine(linePen, origin, target);
     351      }
     352    }
    366353    #endregion
    367 
    368354    #region save image
    369355    private void saveImageToolStripMenuItem_Click(object sender, EventArgs e) {
     
    380366      Image image = new Bitmap(Width, Height);
    381367      using (Graphics g = Graphics.FromImage(image)) {
    382         int height = this.Height / tree.Depth;
    383         DrawFunctionTree(tree, g, 0, 0, Width, height);
     368        DrawFunctionTree(g, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance);
    384369      }
    385370      image.Save(filename);
     
    391376        using (Metafile file = new Metafile(filename, g.GetHdc())) {
    392377          using (Graphics emfFile = Graphics.FromImage(file)) {
    393             int height = this.Height / tree.Depth;
    394             DrawFunctionTree(tree, emfFile, 0, 0, Width, height);
     378            DrawFunctionTree(emfFile, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance);
    395379          }
    396380        }
     
    399383    }
    400384    #endregion
     385    #region export pgf/tikz
     386    private void exportLatexToolStripMenuItem_Click(object sender, EventArgs e) {
     387      var t = Tree;
     388      if (t == null) return;
     389      using (var dialog = new SaveFileDialog { Filter = "Tex (*.tex)|*.tex" }) {
     390        if (dialog.ShowDialog() != DialogResult.OK) return;
     391        string filename = dialog.FileName.ToLower();
     392        var formatter = new SymbolicExpressionTreeLatexFormatter();
     393        File.WriteAllText(filename, formatter.Format(t));
     394      }
     395    }
     396    #endregion
     397
     398    private void reingoldTilfordToolStripMenuItem_Click(object sender, EventArgs e) {
     399      minHorizontalDistance = 30;
     400      minVerticalDistance = 30;
     401      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
     402        NodeWidth = preferredNodeWidth,
     403        NodeHeight = preferredNodeHeight,
     404        HorizontalSpacing = minHorizontalDistance,
     405        VerticalSpacing = minVerticalDistance
     406      };
     407      reingoldTilfordToolStripMenuItem.Checked = true;
     408      boxesToolStripMenuItem.Checked = false;
     409      Repaint();
     410    }
     411
     412    private void boxesToolStripMenuItem_Click(object sender, EventArgs e) {
     413      minHorizontalDistance = 5;
     414      minVerticalDistance = 5;
     415      layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees, n => n.GetLength(), n => n.GetDepth()) {
     416        NodeWidth = preferredNodeWidth,
     417        NodeHeight = preferredNodeHeight,
     418        HorizontalSpacing = minHorizontalDistance,
     419        VerticalSpacing = minVerticalDistance
     420      };
     421      reingoldTilfordToolStripMenuItem.Checked = false;
     422      boxesToolStripMenuItem.Checked = true;
     423      Repaint();
     424    }
    401425  }
    402426}
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.Designer.cs

    r11118 r11120  
    5252      // textBox
    5353      //
    54       this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    55                   | System.Windows.Forms.AnchorStyles.Left)
    56                   | System.Windows.Forms.AnchorStyles.Right)));
     54      this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
     55            | System.Windows.Forms.AnchorStyles.Left)
     56            | System.Windows.Forms.AnchorStyles.Right)));
    5757      this.textBox.BackColor = System.Drawing.Color.White;
     58      this.textBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    5859      this.textBox.Location = new System.Drawing.Point(3, 30);
    5960      this.textBox.Multiline = true;
     
    6667      // formattersComboBox
    6768      //
    68       this.formattersComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
    69                   | System.Windows.Forms.AnchorStyles.Right)));
     69      this.formattersComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
     70            | System.Windows.Forms.AnchorStyles.Right)));
    7071      this.formattersComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
    7172      this.formattersComboBox.FormattingEnabled = true;
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionView.cs

    r11118 r11120  
    7878      UpdateTextbox();
    7979    }
     80
    8081  }
    8182}
  • stable/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNodeConnection.cs

    r10521 r11120  
    2424
    2525namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
    26   public class VisualTreeNodeConnection : object {
     26  public class VisualTreeNodeConnection {
    2727    private static readonly Color defaultLineColor = Color.Black;
    2828    private static readonly DashStyle defaultDashStyle = DashStyle.Solid;
Note: See TracChangeset for help on using the changeset viewer.