4

I'm trying to represent some matrices in a tree. The higher the node of a matrix, the large I want the font to be (and the lower the node, the smaller the font). I came up (in TikzEdt) with

begin{tikzpicture} [
  level 1/.style={level distance=3cm,sibling distance =10cm},
  level 2/.style={level distance=3cm,sibling distance =1.5cm},
  level 3/.style={level distance=1.5cm,sibling distance =0.8cm},
  every node/.style = {shape=rectangle, rounded corners, draw, align=center}
    ]

  \node {\Huge1 0 0\\\Huge 0 1 0\\\Huge0 0 1} 
    child { node {\LARGE1 0 0\\\LARGE1 1 0\\\LARGE1 1 1} 
       child { node {\Large1 0 0\\\Large2 1 0\\\Large3 2 1}  } 
    child { node {1 0 0\\2 0 1\\3 1 2}  }
       child { node {0 1 0\\1 2 0\\2 3 1}  }
       child { node {0 0 1\\1 0 2\\2 1 3}  }
       child { node {0 1 0\\0 2 1\\1 3 2}   }
       child { node [font=\fontsize{140}{120}\selectfont] {0 0 1\\0 1 2\\1 2 3}  }
  }      ;
\end{tikzpicture}

which gives

matrix tree with decreasing fonts

As one can see \Huge, \LARGE and \Large work, apart from the baselineskip, but I want to choose the fonts myself, which I tried in the last matrix. As one can see, the baselineskip {120} works, but the fontsize {140} has not the desired effect.

My TikzEdt preambule is

\documentclass{article}
\usepackage{tikz,amsmath, amssymb,bm,color}
\usepackage[margin=0cm,nohead]{geometry}
\usepackage[active,tightpage]{preview}
%\usepackage{tikz-qtree}
\usepackage[linguistics]{forest}
\usepackage{anyfontsize}
\usetikzlibrary{shapes,arrows,arrows.meta}
\usetikzlibrary{calc,graph}
%\usetikzlibrary{graphdrawing,graphdrawing.trees}
\usepackage{relsize}

My last solution is

\begin{document}

\begin{forest}
  matrices,
  scale fonts=from 45pt to 15pt,
  [1&0&0\\0&1&0\\0&0&1,l sep=1cm
    [1&0&0\\1&1&0\\1&1&1
     [1&0&0\\2&1&0\\3&2&1]
     [1&0&0\\2&0&1\\3&1&2]
     [0&1&0\\1&2&0\\2&3&1]
     [0&0&1\\1&0&2\\2&1&3]
     [0&1&0\\0&2&1\\1&3&2]
     [0&0&1\\0&1&2\\1&2&3]    
    ]
    [1&0&0\\1&0&1\\1&1&1 ,l*=3.5
     [1&0&0\\2&1&1\\3&2&1]
     [1&0&0\\2&1&1\\3&1&2]
     [0&1&0\\1&2&1\\2&3&1]
     [0&0&1\\1&1&2\\2&1&3]
     [0&1&0\\1&2&1\\1&3&2]
     [0&0&1\\1&1&2\\1&2&3]    
    ]
    [0&1&0\\1&1&0\\1&1&1 ,l*=6
     [1&1&0\\2&1&0\\3&2&1]
     [1&0&1\\2&0&1\\3&1&2]
     [1&1&0\\1&2&0\\2&3&1]
     [1&0&1\\1&0&2\\2&1&3]
     [0&1&1\\0&2&1\\1&3&2]
     [0&1&1\\0&1&2\\1&2&3]    
    ]
    [0&0&1\\1&0&1\\1&1&1  ,l*=6
     [1&1&1\\2&1&1\\3&2&1]
     [1&1&1\\2&1&1\\3&1&2]
     [1&1&1\\1&2&1\\2&3&1]
     [1&1&1\\1&1&2\\2&1&3]
     [1&1&1\\1&2&1\\1&3&2]
     [1&1&1\\1&1&2\\1&2&3]    
    ]
    [0&1&0\\0&1&1\\1&1&1 ,l*=3.5
     [1&1&0\\2&2&1\\3&2&1]
     [1&0&1\\2&1&2\\3&1&2]
     [1&1&0\\2&2&1\\2&3&1]
     [1&0&1\\2&1&2\\2&1&3]
     [0&1&1\\1&2&2\\1&3&2]
     [0&1&1\\1&2&2\\1&2&3]    
    ]
    [0&0&1\\0&1&1\\1&1&1
     [1&1&1\\2&2&1\\3&2&1]
     [1&1&1\\2&1&2\\3&1&2]
     [1&1&1\\2&2&1\\2&3&1]
     [1&1&1\\2&1&2\\2&1&3]
     [1&1&1\\1&2&2\\1&3&2]
     [1&1&1\\1&2&2\\1&2&3]
    ]
  ]
\end{forest}  
\end{document}

which givesenter image description here

ArieBos
  • 41
  • 1
    Welcome! You aren't using the code in a comparable place, are you? That is, you're not saying e.g. font=\Huge in the first case. Do you see the same difference if you compare equivalent cases? – cfr Jul 30 '17 at 14:10
  • OK, this is already a large improvement: \node [font=\Huge]{1 0 0\0 1 0\0 0 1} child { node [font=\LARGE] {1 0 0\1 1 0\1 1 1} child { node font=\Large] {1 0 0\2 1 0\3 2 1} } – ArieBos Jul 30 '17 at 14:34
  • 1
    If you add \usepackage{lmodern} (improved replacement for the cm fonts), you get fully scalable fonts and \fontsize works as expected. Allthough that node is not properly adjusted then (and I don't know how to fix this). – Mike Jul 30 '17 at 14:53
  • While it's fine (although not necessary) to add your solution to your question, a better way of showing this is to Accept (and upvote) @cfr 's answer by clicking on the green checkmark beside the voting arrows. – Alan Munn Aug 01 '17 at 15:57

2 Answers2

3

Here's a solution using forest. (I don't know what TikZEdt is.)

This attaches a particular font size to a particular level of the tree. I've also created a command to simplify the input of your matrices: input a comma delimited list of triples and it turns them into a matrix.

\mfmt{100,010,111}

Here's a full example.

\documentclass{article}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{etoolbox}
\usepackage[linguistics]{forest}
\newcommand*{\enormous}{\fontsize{40}{40}\selectfont}
\forestset{node fonts/.style={
   for tree={draw,rounded corners,inner sep=.2em},
   where level=0{font=\enormous}
      {if level=1{font=\large}
         {if level=2{font=\normalsize}
            {if level=3{font=\tiny}
               {font=\footnotesize}}}}}}

    \newcounter{rowcount}
\newcommand*{\addrow}[1]{%
    \stepcounter{rowcount}%
    \ifnum\value{rowcount}<3\scan{#1}\\%
    \else\scan{#1}\fi}
\newcommand{\mfmt}[1]
   {\setcounter{rowcount}{0}%
   \forcsvlist\addrow{#1}%
   \vspace*{-.5ex}}

% This code adapted from https://tex.stackexchange.com/a/233227/2693
\newcommand*\scan[1]{\scanA#1\end}
\newcommand*\scanA[1]{\ifx\end#1\else
   \ifx#1,\relax\else%
   \space#1\space% <- The processing over one token is here
   \fi
   \expandafter \scanA \fi
}

\begin{document}
\begin{forest}node fonts
[\mfmt{100,010,001} [\mfmt{001,010,111} ] [\mfmt{001,010,111} ] [\mfmt{001,010,111} ] [\mfmt{010,111,000} [\mfmt{000,111,010} ] [\mfmt{000,111,010} [\mfmt{000,111,010} ] [\mfmt{000,111,010} ] [\mfmt{000,111,010} ] ] [\mfmt{000,111,010} ]]]
\end{forest}
\end{document}

output of code

Alan Munn
  • 218,180
  • (+1) The scanning stuff is very neat-looking indeed. But possibly an excessive nesting of tabulars? Effectively, you're putting a tabular in another tabular here because linguistics does align=center, if I remember correctly. – cfr Jul 30 '17 at 20:41
  • And, obviously, I can't condone the choice of lmodern :-). – cfr Jul 30 '17 at 20:42
  • @cfr I wrapped things in \tabular because of the extra \ in the last row. But since I have a negative vspace anyway, I could just replace that with a larger value. – Alan Munn Jul 30 '17 at 20:53
  • Yes, but you could just define a different format so you don't get the default tabular as well as yours. That is, define content format so that you control the tabular and aren't putting a tabular inside another tabular cell. – cfr Jul 30 '17 at 21:00
  • @cfr I just got rid of the tabular entirely. I'm still not clear why I need a negative vspace at all. – Alan Munn Jul 30 '17 at 21:24
  • What do you do if you want a double-digit number in a cell of the matrix? – cfr Jul 30 '17 at 22:40
  • @cfr You don't. :) Then you'd need a different input schema anyway, since there's no way to tell how to parse a 4 digit string without an overt delimiter. – Alan Munn Jul 30 '17 at 22:46
  • TikzEdt is simply an editor: http://www.tikzedt.org. BTW, I think it's an excelent tikz editor but, unfortunately, it's no more mantained :( – CarLaTeX Jul 31 '17 at 05:42
1

Here's another Forest version which scales the fonts in each level proportionately. matrices enables the style matrix for the tree. matrix wraps the content in a smallmatrix environment. scale fonts=from <dimension at root> to <dimension at greatest level> scales the fonts between the two given dimensions. For example, scale fonts=from 40pt to 10pt will make the root use 40pt, leaves in the last level use 10pt and all other nodes use something appropriate in between. Obviously, this requires a scalable font.

The advantage of this is that you can add to or reduce the number of levels and the scaling will adjust automatically, but you still have complete control over the smallest and largest fonts in the tree.

If you use a font package such as lmodern (pah!), remove the \tlstyle from the definition else you'll get an error.

Note that you really don't need a special macro to wrap a tabular, array or similar environment around node contents. Forest already includes this functionality. (Indeed, it is used every time you say align=<something>.)

The following is a much-mangled adaption of Alan Munn's answer.

\documentclass[border=10pt]{standalone}
\usepackage{cfr-lm}
\usepackage[linguistics]{forest}
\usepackage{amsmath}
\forestset{
  matrices/.style={
    for tree={
      matrix,
      draw,
      rounded corners,
    },
  },
  matrix/.style={
    content format={%
      \ensuremath{\noexpand\begin{smallmatrix}\forestoption{content}\noexpand\end{smallmatrix}}%
    },
  },
  declare count register={total levels},
  declare dimen register={level incr},
  level incr'=0pt,
  total levels'=0,
  scale fonts/.style args={from #1 to #2}{
    before typesetting nodes={
      total levels/.max={>O{level}}{tree},
      level incr/.process={Rn+dw2+n+d{total levels}{#2-#1}{##2/##1}},
      for tree={
        font/.process={ORw2+nw+dw{level}{level incr}{##1*##2}{##1+#1}{\tlstyle\fontsize{##1}{##1}\selectfont}}
      },
    },
  },
}

\begin{document}
\begin{forest}
  matrices,
  scale fonts=from 40pt to 10pt,
  [1&0&0\\0&1&0\\0&0&1
    [0&0&1\\0&1&0\\1&1&1]
    [0&0&1\\0&1&0\\1&1&1]
    [0&0&1\\0&1&0\\1&1&1]
    [0&1&0\\1&1&1\\0&0&0
      [0&0&0\\1&1&1\\0&1&0]
      [0&0&0\\1&1&1\\0&1&0
        [0&0&0\\1&1&1\\0&1&0]
        [0&0&0\\1&1&1\\0&1&0]
        [0&0&0\\1&1&1\\0&1&0]
      ]
      [0&0&0\\1&1&1\\0&1&0]
    ]
  ]
\end{forest}
\end{document}

scaling fonts

EDIT

Here's a version which uses the comma-split method from Alan's answer, but implements it in Forest.

\documentclass[border=10pt]{standalone}
\usepackage{cfr-lm}
\usepackage[linguistics]{forest}
\usepackage{amsmath}
\forestset{
  matrices/.style={
    for tree={
      matrix,
      draw,
      rounded corners,
    },
  },
  matrix/.style={
    content format={%
      \ensuremath{\noexpand\begin{smallmatrix}\forestoption{content}\noexpand\end{smallmatrix}}%
    },
  },
  declare count register={total levels},
  declare dimen register={level incr},
  level incr'=0pt,
  total levels'=0,
  scale fonts/.style args={from #1 to #2}{
    before typesetting nodes={
      total levels/.max={>O{level}}{tree},
      level incr/.process={Rn+dw2+n+d{total levels}{#2-#1}{##2/##1}},
      for tree={
        font/.process={ORw2+nw+dw{level}{level incr}{##1*##2}{##1+#1}{\tlstyle\fontsize{##1}{##1}\selectfont}}
      },
    },
  },
  add row/.style={
    if rows={}{rows=#1}{rows+=\\#1}
  },
  declare autowrapped toks={rows}{},
  auto matrices/.style={
    matrices,
    before typesetting nodes={
      for tree={
        split option={content}{,}{add row},
        content/.option=rows,
      },
    },
  },
}

\begin{document}
\begin{forest}
  auto matrices,
  scale fonts=from 40pt to 10pt,
  [{1&0&0,0&1&0,0&0&1}
    [{0&0&1,0&1&0,1&1&1}]
    [{0&0&1,0&1&0,1&1&1}]
    [{0&0&1,0&1&0,1&1&1}]
    [{0&1&0,1&1&1,0&0&0}
      [{0&0&0,1&1&1,0&1&0}]
      [{0&0&0,1&1&1,0&1&0}
        [{0&0&0,1&1&1,0&1&0}]
        [{0&0&0,1&1&1,0&1&0}]
        [{0&0&0,1&1&1,0&1&0}]
      ]
      [{0&0&0,1&1&1,0&1&0}]
    ]
  ]
\end{forest}
\end{document}

The output is as above.

cfr
  • 198,882
  • @AlanMunn You don't need etoolbox to split the rows. See above. But splitting within the rows is different. I don't see a nice way to do this without an explicit marker, unless you only ever want single digits in your matrices. – cfr Jul 30 '17 at 22:51
  • Very cool! I had no idea about the split option. – Alan Munn Jul 30 '17 at 22:52
  • Well, that's quite some coding to digest. Will come back to it later. Thnx anyhow. – ArieBos Jul 31 '17 at 09:27
  • I am realy impressed what you guys came up with, but it is (quite) a bit over my head, since I'm not a (La)Tex programmer and have no intention to become one. The first solution I liked most, but understood the least, so I'll stick to the second one. In my answer I'll show how I simplified it. – ArieBos Aug 01 '17 at 15:39