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

Last change on this file since 10520 was 10520, checked in by bburlacu, 5 years ago

#2076: Got rid of layout adapters. Extracted the previous drawing code and made it into another layout engine called the BoxesLayoutEngine (because it divides the areas necessary for each subtree into boxes and recursively applies the layout). Simplified usage of layout engine so that most of the things are handled internally, and the user just has to provide some lambdas telling the engine how to navigate the original tree. Added context option in the SymbolicExpressionTreeChart to choose which layout engine to use for tree drawing. Moved the SymbolicExpressionTreeLatexFormatter to the HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views assembly because it depends on the layout engine.

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.Views {
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
40    public SymbolicExpressionTreeLatexFormatter()
41      : base("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.") {
42      layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> {
43        HorizontalSpacing = 2,
44        VerticalSpacing = 2,
45        NodeWidth = 8,
46        NodeHeight = 4
47      };
48    }
49
50    protected SymbolicExpressionTreeLatexFormatter(SymbolicExpressionTreeLatexFormatter original, Cloner cloner)
51      : base(original, cloner) {
52    }
53
54    public override IDeepCloneable Clone(Cloner cloner) {
55      return new SymbolicExpressionTreeLatexFormatter(this, cloner);
56    }
57
58    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
59      layoutEngine.Reset();
60      var root = symbolicExpressionTree.Root;
61      var actualRoot = root.SubtreeCount == 0 ? root.GetSubtree(0) : root;
62      layoutEngine.Initialize(actualRoot, x => x.Subtrees);
63      layoutEngine.CalculateLayout();
64      var nodeCoordinates = layoutEngine.GetCoordinates();
65      var sb = new StringBuilder();
66      var nl = Environment.NewLine;
67      double ws = 1;
68      double hs = 0.7;
69
70      sb.Append("\\documentclass[class=minimal,border=0pt]{standalone}" + nl +
71                "\\usepackage{tikz}" + nl +
72                "\\begin{document}" + nl +
73                "\\begin{tikzpicture}" + nl +
74                "\\def\\ws{1}" + nl +
75                "\\def\\hs{0.7}" + nl);
76
77      var nodeIndices = new Dictionary<ISymbolicExpressionTreeNode, int>();
78      var nodes = symbolicExpressionTree.IterateNodesBreadth().ToList();
79      for (int i = 0; i < nodes.Count; ++i) {
80        var node = nodes[i];
81        nodeIndices.Add(node, i);
82        var coord = nodeCoordinates[node];
83        var nodeName = symbolNameMap.ContainsKey(node.Symbol.Name) ? symbolNameMap[node.Symbol.Name] : node.ToString();
84        sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\node ({0}) at (\\ws*{1},\\hs*{2}) {{{3}}};", i, ws * coord.X, -hs * coord.Y, EscapeLatexString(nodeName)));
85      }
86
87      for (int i = 0; i < nodes.Count; ++i) {
88        foreach (var s in nodes[i].Subtrees) {
89          sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "\\draw ({0}) -- ({1});", i, nodeIndices[s]));
90        }
91      }
92
93      sb.Append("\\end{tikzpicture}" + nl +
94                "\\end{document}" + nl);
95      return sb.ToString();
96    }
97
98    private static string EscapeLatexString(string s) {
99      return s.Replace("\\", "\\\\").Replace("{", "\\{").Replace("}", "\\}").Replace("_", "\\_");
100    }
101  }
102}
Note: See TracBrowser for help on using the repository browser.