Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Include TikZ code in bookdown figure environment

I'd like to add a TikZ figure to a bookdown document in order to include some fancy graphics.

My primary output format is LaTeX which means that I could essentially just include the TikZ graphics verbatim in the Rmarkdown file and it would render fine. However, two problems are haunting me:

  • I'd like for the TikZ graphics to be part of a figure environment (for the numbering, caption etc).
  • I'd like to be able to render the same code to both PDF (LaTeX) and Gitbook (HTML).

Right now I have the following chunk which nicely produces the relevant graph as a figure when I render to pdf.

```{r, echo=FALSE, engine='tikz', out.width='90%', fig.ext='pdf', fig.cap='Some caption.'}
\begin{tikzpicture}[scale=.7]
\draw [fill=gray!30,very thick] (0,-1) rectangle (5,1);
\draw [very thick] (5, 0) -- (13,0);
\node [below] at (2,-1) {\large Hello};
\node [below, align=center] at (0,-1) {\large Two\\ lines};
\end{tikzpicture}
```

However, there are two problems with the code:

  1. I do not get any output when rendering to gitbook (using knitr and bookdown). I do get the figure caption, however, and if I render to html_document then it works too and I can see the graph.
  2. For PDF the text is rendered using the computer modern font. I'd really like to change this, and the main font in the LaTeX document has already been set to something else. However, because the code is rendered locally by the TikZ engine and then inserted, it is not part of the full LaTeX document. Can I add some LaTeX options, packages etc. that are included by the TikZ engine before the code is rendered?

If there are other ways to include the TikZ code as part of a figure environment then I'd be happy to know.

Update: I guess the second point could be fixed by setting engine.opts = list(template = "latex/tikz2pdf.tex") where the necessary setup for LaTeX is included in the tikz2pdf.tex file. That file is read using LaTeX but I'd like to use xelatex to parse the file since I'm using the fontspec LaTex package. Can that be changed anyway?

like image 728
ekstroem Avatar asked Nov 17 '17 20:11

ekstroem


1 Answers

I think I found an answer to both of my questions. It did take - as Yihui pointed out - quite some time. I'm including the answer here in case someone else turns out to need this (or myself at a later point).

Re 1) Render TikZ code to both pdf and gitbook

This turned out to be easier than I anticipated. Setting the argument fig.ext=if (knitr:::is_latex_output()) 'pdf' else 'png' as part of the chunk arguments helps this along. If I'm not knitting to PDF then imagemagick or some other software automatically converts it to PNG.

Re 2) Modifying the font

As listed in my updated question this can be set by tweaking the file tikz2pdf.tex that is part of knitr. A copy of it is included below so you don't have to search for it yourself. Setting the chunk argument engine.opts = list(template = "latex/tikz2pdf.tex") enables you to put any desired fonts, LaTeX packages etc in preamble before the TikZ code is rendered.

Looking through the knitr code, you can see that texi2dvi is used to parse the tikz2pdf.tex file with the TikZ code inserted. texi2dvi calls pdflatex which messes things up in case you need to use XeLaTeX or LuaLaTeX to include TrueType fonts using fontspec.

I'm sure it would be possible to fix that somehow in the texi2dvi code but a much simpler solution (at least for me) was to change the environment. If I set the two environmental variable before starting R and rendering the book then xelatex is automatically used for compiling all the code. In my bash terminal this is done using

export LATEX="xelatex"
export PDFLATEX="xelatex"

Voila!

The chunk becomes

```{r, echo=FALSE, engine='tikz', out.width='90%', fig.ext=if (knitr:::is_latex_output()) 'pdf' else 'png', fig.cap='Some caption.', engine.opts = list(template = "latex/tikz2pdf.tex")
}
\begin{tikzpicture}[scale=.7]
\draw [fill=gray!30,very thick] (0,-1) rectangle (5,1);
\draw [very thick] (5, 0) -- (13,0);
\node [below] at (2,-1) {\large Hello};
\node [below, align=center] at (0,-1) {\large Two\\ lines};
\end{tikzpicture}
```

and tikz2pdf.tex is

\documentclass{article}
\include{preview}
\usepackage[pdftex,active,tightpage]{preview}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{matrix}
%% INSERT YOUR OWN CODE HERE 
\begin{document}
\begin{preview}
%% TIKZ_CODE %%
\end{preview}
\end{document}

I'm still surprised at the whole flexibility of knitr and related packages. Nice work Yihui!

like image 85
ekstroem Avatar answered Oct 05 '22 23:10

ekstroem