13

Two questions really ... (fishing for lots of opinions here)

  1. Is there a definitive guide that most folks agree is the best place to come up to speed on how to make pictures in the tikz world, and

  2. in particular, how one would use it (assuming it's not self-evident) to make images like the ones below? (Assuming that tikz is the best way to go other than just inserting eps images in LaTeX)

enter image description here

  • 7
    The PGF/TikZ manual is not only the definitive reference for PGF/TikZ, it also contains a couple of very gentle tutorials that will help get you started. – Jake Jun 15 '13 at 22:06
  • 3
    Also have a look at our in house cheat sheet tex.stackexchange.com/questions/84753/summary-of-tikz-commands – percusse Jun 15 '13 at 23:41
  • Should the shaded sub-regions in each shape be variable or you just want those exact shapes? – Gonzalo Medina Jun 16 '13 at 0:48
  • Yes and no ... I do need to "slice" the quartered circle in half and sandwich a quartered square in between. Making a quartered circle has been quite simple; but the quartered square is not been so cooperative. Here's my circle code. \begin{tikzpicture} % The quartered circle \draw (-1,0) -- (1,0); \draw (0,-1) -- (0,1); \draw (0,0) circle (1cm); \shadedraw[left color=gray,right color=gray, draw=gray!50!black] (0,0) -- (1cm,0mm) arc (0:90:1cm) -- cycle; \end{tikzpicture} – Clark Jun 16 '13 at 1:07
  • my apologies for the code snippet ... I expected a different format output. – Clark Jun 16 '13 at 1:12
14
  1. As Jake has mentioned in his comment, the PGF/TikZ manual is the definitive reference for PGF/TikZ, and it contains some very gentle tutorials that will help get you started. There's also a Minimal Introduction to TikZ which could be helpful (I've never read it). Another valuable source of examples would be the gallery in TeXample.net. And, last but not least, this site contains a great collection of examples ranging from asimple to very sophisticated.

  2. There are many possibilities to construct the required shapes; I opted for defining some commands \MySquare and \MyCircle each one having five arguments; the first argument gives the length of the side of the square (the diameter of the circle, respectively), and the other four arguments can be used to fill a quadrant. The \MyShape command has nine arguments; the first one controlling the size and the other eight used for the filling colors.

In all three cases the idea is the same; first, the regions are shaded, then the shape and the divisory lines are drawn.

The code:

\documentclass[12pt]{article}
\usepackage{tikz}

\newcommand\FillSquare[5]{%
\fill[#2] (0,0) rectangle +(0.5*#1,0.5*#1);
\fill[#3] (0.5*#1,0cm) rectangle +(0.5*#1,0.5*#1);
\fill[#4] (0,0.5*#1) rectangle +(0.5*#1,0.5*#1);
\fill[#5] (0.5*#1,0.5*#1) rectangle +(0.5*#1,0.5*#1);
}

\newcommand\MySquare[5]{%
\FillSquare{#1}{#2}{#3}{#4}{#5}
\draw (0,0) rectangle (#1,#1);
\draw (0,0.5*#1) -- +(#1,0);
\draw (0.5*#1,0) -- +(0,#1);
}

\newcommand\MyCircle[5]{%
\fill[#4] (0,0) arc[radius=0.5*#1,start angle=180,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#5] (#1,0) arc[radius=0.5*#1,start angle=0,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#3] (#1,0) arc[radius=0.5*#1,start angle=0,end angle=-90] -- +(0,0.5*#1) -- cycle;
\fill[#2] (0.5*#1,-0.5*#1) arc[radius=0.5*#1,start angle=-90,end angle=-180] -- +(0.5*#1,0) -- cycle;
\draw (0.5*#1,0) circle [radius=0.5*#1];

\draw (0,0) -- +(#1,0);
\draw (0.5*#1,-0.5*#1) -- +(0,#1);
}

\newcommand\MyShape[9]{%
\fill[#2] (0,0) arc[radius=0.5*#1,start angle=270,end angle=180] -- +(0.5*#1,0) --cycle;
\fill[#5] (-0.5*#1,0.5*#1) arc[radius=0.5*#1,start angle=180,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#6] (1.5*#1,0.5*#1) arc[radius=0.5*#1,start angle=0,end angle=90] -- +(0,-0.5*#1) --cycle;
\fill[#9] (1.5*#1,0.5*#1) arc[radius=0.5*#1,start angle=0,end angle=-90] -- +(0,0.5*#1) -- cycle;
\FillSquare{#1}{#3}{#4}{#7}{#8}
\draw (#1,0) -- +(-#1,0) 
  arc[radius=0.5*#1,start angle=270,end angle=90] -- +(#1,0)
  arc[radius=0.5*#1,start angle=90,end angle=-90] -- cycle;
\draw (-0.5*#1,0.5*#1) -- +(2*#1,0);
\draw (#1,0) -- +(0,#1);
\draw (0.5*#1,0) -- +(0,#1);
\draw (0,0) -- +(0,#1);
}

\begin{document}

\begin{tikzpicture}
\MySquare{4cm}{gray!30}{blue!30}{green!30}{red!30}
\begin{scope}[xshift=5.2cm,yshift=1cm] 
\MyCircle{2cm}{orange}{gray!30}{red!30}{cyan}
\end{scope}
\begin{scope}[xshift=2.2cm,yshift=-4cm] 
\MyShape{3cm}{gray!30}{blue!30}{green!30}{red!30}{olive!60}{brown!30}{yellow!30}{cyan!50}
\end{scope}
\end{tikzpicture}

\end{document}

enter image description here

If labels have to be added to the regions, perhaps a different approach is better:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}

\newcommand\DrawSquare[3][]{%
\node[inner sep=0pt,outer sep=0pt,draw,rectangle,minimum size=#2,#1] (#3) {}; 
}

\newcommand\FillSquare[3]{%
\ifnum#2=1\relax
  \fill[#3] ( $ (#1.north west) + (0.5\pgflinewidth,-0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=2\relax
  \fill[#3] (#1.center) rectangle ( $ (#1.north east) + (-0.5\pgflinewidth,-0.5\pgflinewidth) $ );
\else
\ifnum#2=3\relax
  \fill[#3] ( $ (#1.south west) + (0.5\pgflinewidth,0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=4\relax
  \fill[#3] (#1.center) rectangle ( $ (#1.south east) + (-0.5\pgflinewidth,0.5\pgflinewidth) $ );
\fi\fi\fi\fi%
}

\newcommand\LabelRegion[3]{%
\ifnum#2=1\relax
\node at ( $ (#1.north west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=2\relax
\node at ( $ (#1.north east)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=3\relax
\node at ( $ (#1.south west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=4\relax
\node at ( $ (#1.south east)!0.5!(#1.center) $ ) {#3};
\fi\fi\fi\fi%
}

\newcommand\DrawLines[1]{%
\draw (#1.north) -- (#1.south);
\draw (#1.west) -- (#1.east);
}

\begin{document}

\begin{tikzpicture}
\DrawSquare{3cm}{A}
\FillSquare{A}{1}{red!40}
\FillSquare{A}{2}{blue!40}
\FillSquare{A}{3}{green!40}
\FillSquare{A}{4}{yellow!40}
\DrawLines{A}
\LabelRegion{A}{1}{I}
\LabelRegion{A}{2}{II}
\LabelRegion{A}{3}{III}
\LabelRegion{A}{4}{IV}
\DrawSquare[right=of A]{2cm}{B}
\FillSquare{B}{1}{gray!40}
\FillSquare{B}{2}{orange!40}
\FillSquare{B}{3}{cyan!40}
\FillSquare{B}{4}{magenta!40}
\DrawLines{B}
\LabelRegion{B}{1}{a}
\LabelRegion{B}{2}{b}
\LabelRegion{B}{3}{c}
\LabelRegion{B}{4}{d}
\end{tikzpicture}

\end{document}

enter image description here

The commands:

\DrawSquare{<length>}{<name>}

draws a square of side equal to <length> and assigns to it the name <name>; it has an optional argument to pass options to the \node used to draw the square.

\FillSquare{<name>}{<number>}{<color>}

Fills one of the four quadrants of the square with name <name>, using the color specified in the third argument. <number> is an integer number from 1 to 4 controlling which region will be colored.

Additional labels can be assigned using the anchors associated to the <name> used to name the square.

\DrawLines{<name>}

draws two perpendicular lines for the node named <name>.

Finally,

\LabelRegion{<name>}{<number>}{<text>}

places <text> in the center of region <number> for the shape named <name>.

Using some \foreach loops the code simplifies even more:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}

\newcommand\DrawSquare[3][]{%
\node[inner sep=0pt,outer sep=0pt,draw,rectangle,minimum size=#2,#1] (#3) {}; 
}

\newcommand\FillSquare[3]{%
\ifnum#2=1\relax
  \fill[#3] ( $ (#1.north west) + (0.5\pgflinewidth,-0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=2\relax
  \fill[#3] (#1.center) rectangle ( $ (#1.north east) + (-0.5\pgflinewidth,-0.5\pgflinewidth) $ );
\else
\ifnum#2=3\relax
  \fill[#3] ( $ (#1.south west) + (0.5\pgflinewidth,0.5\pgflinewidth) $ ) rectangle (#1.center);
\else
\ifnum#2=4\relax
  \fill[#3] (#1.center) rectangle ( $ (#1.south east) + (-0.5\pgflinewidth,0.5\pgflinewidth) $ );
\fi\fi\fi\fi%
}

\newcommand\LabelRegion[3]{%
\ifnum#2=1\relax
\node at ( $ (#1.north west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=2\relax
\node at ( $ (#1.north east)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=3\relax
\node at ( $ (#1.south west)!0.5!(#1.center) $ ) {#3};
\else
\ifnum#2=4\relax
\node at ( $ (#1.south east)!0.5!(#1.center) $ ) {#3};
\fi\fi\fi\fi%
}

\newcommand\DrawLines[1]{%
\draw (#1.north) -- (#1.south);
\draw (#1.west) -- (#1.east);
}

\newcommand\ColorRegions[2]{%
\foreach \rcolor [count=\i] in {#2}
  {\FillSquare{#1}{\i}{\rcolor}}
}

\newcommand\PlaceLabels[2]{%
\foreach \rlabel [count=\i] in {#2}
  {\LabelRegion{#1}{\i}{\rlabel}}
}

\begin{document}

\begin{tikzpicture}
\DrawSquare{3cm}{A}
\ColorRegions{A}{red!40,blue!40,green!40,yellow!40}
\DrawLines{A}
\PlaceLabels{A}{I,II,III,IV}

\DrawSquare[right=of A]{2cm}{B}
\ColorRegions{B}{gray!40,orange!40,cyan!40,magenta!40}
\DrawLines{B}
\PlaceLabels{B}{a,b,c,d}
\end{tikzpicture}

\end{document}
  • Cool! OK...I'm reading up on how to label sections, and am wondering if the node placement (relative) and then the label attribute is the best way to go, or is there something better? – Clark Jun 16 '13 at 3:00
  • And I think I'm halfway lost on (1) the syntax for positioning, and (2) how the code sections like \newcommand\MyCircle[5] and \fill[#4] are connected. It's probably buried in the resources suggested above, but I'm missing it for some reason. For example, laying them all out horizontally where it's square plus circle equals the pill. – Clark Jun 16 '13 at 3:18
  • @Clark you didn't mention anything about labels in your question, so I only focused on the drawing. If you want some labels, perhaps there could be a better approach. Please edit your question and state precisely what you need. For the other comment \newcommand\MyCircle[5]{<definition>} means that \MyCircle will have 5 mandatory arguments; inside the <definition> part you refer to these arguments using #, so for example, #3 refers to the third argument. – Gonzalo Medina Jun 16 '13 at 17:19
  • Sorry ... it hit me later. Next time I'll start a new question. And thanX for the [argument] explanation ... I was trying to determine what the [#?] referred to ... an array, list, etc. It made some sense at face value, but I was still in the mode of looking up all the syntax for \draw and \path etc. – Clark Jun 16 '13 at 20:34
  • @Clark I've added another approach to my answer. With this new code, labeling the regions is simpler than with the previous approach. – Gonzalo Medina Jun 16 '13 at 21:43
4

Here is a solution that can be applied to every path (including paths of nodes).

This includes one key: divide (and a few auxiliary keys).

Its syntax is a list of lists:

[divide={{gray!30:I,blue!30:II},{green!30:III,red!30:[green]IV}}]

means that the first line is

{gray!30:I,blue!30:II}

and the second line is

{green!30:III,red!30:[green]IV}.

The result is seen below.

The code also checks for various other keys for ever row and every column and every cell.

The same applies for the node that is placed in the sections (which I wasn’t aware of before you commented this on the other answer). This may be better done with only nodes that span the entire sections.

The calculation of the auxiliary coordinates could be improvement by using low-level PGF commands.

Code

\documentclass[tikz,convert=false]{standalone}
\usepackage{etoolbox}
\usetikzlibrary{calc,shapes.misc}
\makeatletter
\def\qrr@ppbb{path picture bounding box}
\tikzset{
  divide/.style={%
    /utils/exec=%
      \let\qrr@pathpicture\pgfutil@empty
      \pgfutil@tempcnta\z@ % rows
      \pgfutil@tempcntb\z@,% cols
    /tikz/@divide rows/.list={#1},
    path picture/.expand once=\qrr@pathpicture
  },
  @divide rows/.style={%
    /utils/exec=\pgfutil@tempcntb\z@,
    @divide cols/.list={#1},
    /utils/exec=\advance\pgfutil@tempcnta\@ne
  },
  @divide cols/.code=
    \let\pgf@tempb\pgfutil@empty
    \let\pgf@tempc\pgfutil@empty
    \pgfutil@in@{:}{#1}%
    \ifpgfutil@in@
      \pgfkeysalso{@divide cols split={#1}}%
    \else
      \def\pgf@tempa{#1}%
    \fi
    \eappto\qrr@pathpicture{%
      \noexpand\path
            ($(\qrr@ppbb.north west)!\the\pgfutil@tempcntb/\noexpand\the\pgfutil@tempcntb!(\qrr@ppbb.north east)$)
            coordinate (qrr@pp@tl)
            ($(\qrr@ppbb.north west)!\number\numexpr\pgfutil@tempcntb+\@ne\relax/\noexpand\the\pgfutil@tempcntb!(\qrr@ppbb.north east)$)
            coordinate (qrr@pp@tr)
            ($(\qrr@ppbb.north west)!\the\pgfutil@tempcnta/\noexpand\the\pgfutil@tempcnta!(\qrr@ppbb.south west)$)
            coordinate (qrr@pp@lt)
            ($(\qrr@ppbb.north west)!\number\numexpr\pgfutil@tempcnta+\@ne\relax/\noexpand\the\pgfutil@tempcnta!(\qrr@ppbb.south west)$)
            coordinate (qrr@pp@bl);
      \noexpand\path[
        every divide/.try,
        every divide \the\pgfutil@tempcntb\space row/.try,
        every divide \the\pgfutil@tempcnta\space column/.try,
        every divide \the\pgfutil@tempcntb-\the\pgfutil@tempcntb\space cell/.try,
        \pgf@tempa,
        every divide later/.try,
        every divide \the\pgfutil@tempcntb\space row later/.try,
        every divide \the\pgfutil@tempcnta\space column later/.try,
        every divide \the\pgfutil@tempcntb-\the\pgfutil@tempcntb\space cell later/.try,
        midway
        ] (qrr@pp@tl |- qrr@pp@lt) 
          coordinate (cell-\the\pgfutil@tempcntb-\the\pgfutil@tempcnta-tl)
          rectangle (qrr@pp@tr |- qrr@pp@bl) 
          coordinate (cell-\the\pgfutil@tempcntb-\the\pgfutil@tempcnta-br)
          \ifx\pgf@tempc\pgfutil@empty\else
            node[
              every divide node/.try,
              every divide \the\pgfutil@tempcntb\space row node/.try,
              every divide \the\pgfutil@tempcnta\space column node/.try,
              every divide \the\pgfutil@tempcntb-\the\pgfutil@tempcntb\space cell node/.try,
              \expandafter\unexpanded\expandafter{\pgf@tempb}] {\expandafter\unexpanded\expandafter{\pgf@tempc}}
          \fi
          ;
    }%
    \advance\pgfutil@tempcntb\@ne,
  @divide cols split/.code args={#1:#2}{
    \def\pgf@tempa{#1}%
    \pgfutil@ifnextchar[\qrr@divide@splitopt{\qrr@divide@splitopt[]}#2\@qrr@divide@splitopt
  }
}
\def\qrr@divide@splitopt[#1]#2\@qrr@divide@splitopt{\def\pgf@tempb{#1}\def\pgf@tempc{#2}}
\makeatother
\tikzset{every divide node/.style={midway,text=black}}
\begin{document}
\tikz[every divide/.style={fill}] \draw (0,0) rectangle (2,3) [divide={{gray!30:I,blue!30:II},{green!30:III,red!30:IV}}];
\tikz[every divide/.style={fill},every divide later/.style={draw=black}] \draw (1,2) circle [x radius=2, y radius=3] [divide={{gray!30,blue!30},{green!30,red!30}}];
\tikz[every divide/.style={fill,sharp corners}] \draw[rounded corners=1cm] (0,0) rectangle (2,3) [divide={{gray!30,blue!30},{green!30,red!30}}];
\tikz[every divide/.style={fill,sharp corners}] \node[draw,minimum size=3cm, minimum height=1.5cm, rounded corners=.5cm,divide={{gray!30,blue!30,yellow},{green!30,red!30,blue}}] {};

\begin{tikzpicture}
\node[draw,rounded rectangle,minimum size=4cm,minimum height=2cm,
  divide={{draw,draw=gray!75!black,{fill=gray,draw=gray!75!black},{draw,fill=gray}},{draw,,draw=gray!75!black,draw}}
] (n) {};
\draw (cell-1-0-tl) -- (cell-1-0-tl |- cell-1-0-br);
\end{tikzpicture}
\end{document}

Output

enter image description here enter image description here enter image description here enter image description here

Third example that is very large.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.