source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs @ 10496

Last change on this file since 10496 was 10496, checked in by bburlacu, 6 years ago

#2076: Integrated the Reingold-Tilford layout into the trunk.

File size: 4.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Globalization;
25using System.Linq;
26using System.Text;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29
30namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
31  [Item("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.")]
32  public class SymbolicExpressionTreeLatexFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
33    private readonly static Dictionary<string, string> symbolNameMap = new Dictionary<string, string>
34    {
35      {"ProgramRootSymbol", "Prog"},
36      {"StartSymbol","RPB"}
37    };
38    private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>();
39    private readonly SymbolicExpressionTreeLayoutAdapter layoutAdapter = new SymbolicExpressionTreeLayoutAdapter();
40
41    public SymbolicExpressionTreeLatexFormatter()
42      : base("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.") {
43      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>();
44    }
45
46    protected SymbolicExpressionTreeLatexFormatter(SymbolicExpressionTreeLatexFormatter original, Cloner cloner)
47      : base(original, cloner) {
48    }
49
50    public override IDeepCloneable Clone(Cloner cloner) {
51      return new SymbolicExpressionTreeLatexFormatter(this, cloner);
52    }
53
54    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
55      layoutEngine.Reset();
56      var layoutNodes = layoutAdapter.Convert(symbolicExpressionTree).ToList();
57      layoutEngine.Root = layoutNodes[0];
58      layoutEngine.AddNodes(layoutNodes);
59      layoutEngine.CalculateLayout();
60      var nodeCoordinates = layoutEngine.GetNodeCoordinates();
61      var sb = new StringBuilder();
62      var nl = Environment.NewLine;
63      double ws = 1;
64      double hs = 0.7;
65
66      sb.Append("\\documentclass[class=minimal,border=0pt]{standalone}" + nl +
67                "\\usepackage{tikz}" + nl +
68                "\\begin{document}" + nl +
69                "\\begin{tikzpicture}" + nl +
70                "\\def\\ws{1}" + nl +
71                "\\def\\hs{0.7}" + nl);
72
73      var nodeIndices = new Dictionary<ISymbolicExpressionTreeNode, int>();
74      var nodes = symbolicExpressionTree.IterateNodesBreadth().ToList();
75      for (int i = 0; i < nodes.Count; ++i) {
76        var node = nodes[i];
77        nodeIndices.Add(node, i);
78        var coord = nodeCoordinates[node];
79        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
80        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1},\\hs*{2}) {{{3}}};", i, ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
81      }
82
83      for (int i = 0; i < nodes.Count; ++i) {
84        foreach (var s in nodes[i].Subtrees) {
85          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", i, nodeIndices[s]));
86        }
87      }
88
89      sb.Append("\\end{tikzpicture}" + nl +
90                "\\end{document}" + nl);
91      return sb.ToString();
92    }
93
94    private static string EscapeLatexString(string s) {
95      return s.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}").Replace("_", "\\_");
96    }
97  }
98}
Note: See TracBrowser for help on using the repository browser.