Making Beautiful Schematics with TikZ


I have always been a fan of using LaTeX for all of my writeups. LaTeX has a fantastic graphical library called TikZ that I use to generate nearly all of my graphics. It has quite a steep learning curve, but once you get going, you can define all of your variables programmatically at the top of your file, and quickly edit them when you change the parameters of an experiment.

If you're really fancy, you can do all of that with Python, but we won't go that far today.

You're going to need to install LaTeX. Once you have LaTeX installed, grab TikZ Editor for Mac/Linux, or TikzEdt for Windows.

If everything is successful, you should be able to drop in the code from this example at texexample.com and see the following graphic:

% Optical Fiber Polarization Controller
% Author: Jimi Oke
\documentclass{article}
\usepackage{tikz}
%%%<
\usepackage{verbatim}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{5pt}%
%%%>
\begin{comment}
:Title: Optical Fiber Polarization Controller
:Tags: Foreach; Scopes
:Author: Jimi Oke
:Slug: polarization-controller

A polarization controller is an optical device for modifying the polarization state of light. This is a simplified 3-D diagram of an optical fiber polarization controller.
\end{comment}
\begin{document}
\begin{tikzpicture}[x={(0.866cm,-0.5cm)},
  y={(0.866cm,0.5cm)}, z={(0cm,1cm)}]
\tikzstyle{paddle}=[very thick, fill=white]
\coordinate (O) at (0, 0, 0);

% fiber in
\draw[thick] (0,-1.5,0) to[out=30,in=220] (1,0,0);

% first divider
\draw[fill=white] (1,-.4,-.5) -- (2,-.4,-.5) -- (2,-.4,.25) --
      (1,-.4,.25) -- (1,-.4,-.5)
      (2,-.4,.25) -- (2,.4,.25) -- (1,.4,.25) -- (1,-.4,.25)
      (2,.4,.25) -- (2,.4,-.5) -- (2,-.4,-.5);

% first paddle
\draw[paddle]
      (2,0,0) -- (4,0,0) -- (4,2,0) -- (2,2,0) -- (2,0,0) % first face
      (2,0,0) -- (2,0,-.1)
      (4,0,0) -- (4,0,-.1)
      (2,0,-.1) -- (4,0,-.1) -- (4,2,-.1);
\draw (3,1,0) circle (.94)
      (3,1,0) circle (.9);

% second divider
\draw[fill=white] (4,-.4,-.5) -- (5,-.4,-.5) -- (5,-.4,.25) --
      (4,-.4,.25) -- (4,-.4,-.5)
      (5,-.4,.25) -- (5,.4,.25) -- (4,.4,.25) -- (4,-.4,.25)
      (5,.4,.25) -- (5,.4,-.5) -- (5,-.4,-.5);

% second paddle
\filldraw[paddle]
     (5,0,0) -- (7,0,0) -- (7,0,2) -- (5,0,2) -- (5,0,0) % first face
     (7,0,0) -- (7,.1,0) -- (7,.1,2) -- (5,.1,2) -- (5,0,2)
     (7,.1,2) -- (7,0,2);

% third divider
\draw[fill=white] (7,-.4,-.5) -- (8,-.4,-.5) -- (8,-.4,.25) --
      (7,-.4,.25) -- (7,-.4,-.5)
      (8,-.4,.25) -- (8,.4,.25) -- (7,.4,.25) -- (7,-.4,.25)
      (8,.4,.25) -- (8,.4,-.5) -- (8,-.4,-.5);

% third paddle
\filldraw[paddle]
     (8,0,0) -- (10,0,0) -- (10, -1.732,1) -- (8,-1.732,1)
     -- (8,0,0)
(8,-1.732,1) -- (8,-1.732,.9) -- (10,-1.732,.9) -- (10,0,-.1)
-- (10,0,0)
(10,-1.732,.9) -- (10,-1.732,1);

% fourth divider
\draw[fill=white] (10,-.4,-.5) -- (11,-.4,-.5) -- (11,-.4,.25) --
      (10,-.4,.25) -- (10,-.4,-.5)
      (11,-.4,.25) -- (11,.4,.25) -- (10,.4,.25) -- (10,-.4,.25)
      (11,.4,.25) -- (11,.4,-.5) -- (11,-.4,-.5);

\begin{scope}[x={(0.866cm,-0.5cm)},y={(0,1cm)}]
\draw (6,0,1) circle (.94)
      (6,0,1) circle (.9);
\end{scope}

\begin{scope}[x={(0.866cm,-0.5cm)},y={(-.73cm,.077cm)}]
\draw[fill=white] (9,1) circle (.94)
      (9,1) circle (.9);
\end{scope}

% fiber exit
\draw (11,-.05,.05) -- (11,.05,.05) --
     (11,.05,-.05) -- (11,-.05,-.05) -- (11,-.05,.05);
\draw[thick] (10.95,0,0) to[out=-30,in=180] (12,1,-1);
\end{tikzpicture}
\end{document}

Once you have your Tikz editor set up, now all you need is a way to quickly convert from LaTeX into PDFs and SVGs. Compiling into PDF is rather trivial. There is also a command line tool called pdf2svg that will (epynomously) convert PDFs into SVGs. On Unix devices, you can install it using a package manager. For example, on Mac:

brew install pdf2svg

Finally, I wrote a little BASH script that lives in my ~/.bashrc file that converts all of the .tex files in a directory into PDFs and SVGs whenever I type 'tex2svg' in a terminal. Here's the code.

tex2svg(){
    # Converts any .tex files in the directory into
    # pdf and svg files

    files=(*.tex)
    echo ${files[@]}

    for filename in "${files[@]}"
    do
        # not used, but helpful if you want to extend
        # this script for some reason...
        extension="${filename##*.}"

        filename="${filename%.*}"
        pdflatex "$filename.tex"
        pdf2svg "$filename.pdf" "$filename.svg"
    done
}