Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to draw various matchstick pictures like this:

enter image description here

or like this

or other figures from: http://www.quizfragen4kids.de/figuren-sinnes-bilderraetsel/streichholz-spiele-knobeleien-1.html

I want to use tikz for this and have two questions about this:

  • How do I get the path decoration with the matchsticks?
  • What's the (syntactically) easiest way to draw pictures like this or how would a tikz expert do this (to be flexible enough to draw such kind of figures but to have an easy syntax)?
share|improve this question

5 Answers 5

up vote 46 down vote accepted

Here's an alternative way using decorations. Match sticks are drawn on each input segment, so multiple matches can be drawn with one path. The decoration definition is a bit messy but unavoidably so in order to get the shadow opacity right.

EDITS 1 & 2: The decoration definition has been changed to make things a bit cleaner/customisable:

\documentclass[tikz,border=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{fadings}
\usetikzlibrary{decorations}

\pgfdeclaredecoration{match stick}{draw}{
    \state{draw}[width=\pgfdecoratedinputsegmentlength]{
        \tikzset{x=\pgfdecoratedinputsegmentlength/10, y=\pgfdecorationsegmentamplitude/2}
        \begin{scope}[transparency group, match shadow/.try]
            \path [fill=match shadow, match stick path/.try];
            \path [fill=match shadow, match head path/.try];
        \end{scope}
        \path [match stick/.try, match stick path/.try];
        \path [match head/.try, match head path/.try];
    }
}

\tikzset{
    match/.style={
        decoration={match stick, amplitude=2pt}, decorate
    },
    % The match stick is scaled so that
    % 1 x-unit = \pgfdecoratedinputsegmentlength/10
    % 1 y-unit = \pgfdecorationsegmentamplitude/2
    match stick path/.style={
        insert path={(1.375,-1) rectangle (8.375,1)}
    },
    match head path/.style={
        insert path={(8.375,0) ellipse [x radius=0.625, y radius=1.25]}
    },
    match shadow color/.code=\colorlet{match shadow}{#1},
    match shadow color=gray,
    match shadow/.style={
        transform canvas={shift=(330:1pt)},
        opacity=0.5,
    },
    match stick/.style={
        fill=yellow
    },
    match head/.style={
        fill=red
    }
}
\begin{document}
\tikz\path [match] 
    % tail
    (135:1) -- (0,0) 
    % body
    (0,0) -- (1,0) -- (2,0) -- (2,-1) --
    (1,-1) -- (0,-1) 
    (0,0) -- (0,-1)
    % back legs
    (0,-1) -- ++(250:1) (0,-1) -- ++(290:1)
    % front legs
    (2,-1) -- ++(250:1) (2,-1) -- ++(290:1)
    % nose
    (2,0)  -- ++(340:1)
    (2,-1) -- ++(45:1);

\tikz\foreach \p in {(0:0),(60:1),(60:2), (0:1),(0:2), (30:sqrt 3)}
    \path [match, shift={\p}] (0,0) -- (60:1) -- (0:1) (0,0) -- (0:1);

\end{document}

enter image description here

enter image description here

share|improve this answer

EDIT At the end there is a better solution for the shadows problem.

Here is an idea which combines several hacks.

  1. For the match shape, use the cylinder node shape, with yellow body and red top. A drop shadow should be nice too, but for some reason it makes the cylinder to appear translucent...

  2. You can make that node shape to be used as a straight line in a path, if you draw the node midway, sloped, and give it as minimum height the distance among the two ends of the intended path. In fact, you can give only a 80% of that distance, to create a gap at the ends (kind of shorten > and shorten <)

  3. I think that the easiest way to specify the coordinates of a match is to give the cartesian coordinates of the beginning of the match, and then the polar coordinates of the other end with respect to its beginning. That is, for example: \match{3,2}{60:3} represents a match which starts at (3,2), and points in an angle of 60 and has a length of 3. This ensures that all matches are drawn with the same length, even if they are not perpendicular or in a grid.

I combined these ideas in the following code:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\usetikzlibrary{shapes.geometric,shadows,calc}

\tikzset{
  match/.style = {
    cylinder,
    shape aspect = 1.5,
    cylinder uses custom fill,
    cylinder body fill=yellow,
    cylinder end fill = red,
    inner sep = 0pt,
    minimum width = 2mm,
    draw = black!20!yellow,
    sloped, midway,
    drop shadow={
     shadow yshift=-.7mm, shadow xshift=.5mm, opacity=.4},
   }
}

\def\match#1#2{
\path let
    \p1=(#2),
    \n1={0.8*veclen(\p1)}
    in (#1) -- +(#2)
    node[match,minimum height=\n1] {\phantom{x}}; % phantom is required, without it the end of the cylinder is not drawn (?)
}

\begin{tikzpicture}
\foreach \a in {0,30,...,359} { 
  \match{0,0}{\a:3}
} 
\begin{scope}[xshift=4cm,yshift=-3cm]
  \foreach \i in {0,3,...,9} {
    \foreach \j in {0,3} {
      \match{\i,\j}{0:3}
      \match{\i,\j}{90:3}
    }
  }
  \foreach \i in {0,3,...,9} {
      \match{\i,6}{0:3}
  }
\end{scope}
\end{tikzpicture}
\end{document}

Result

Another example :-)

\begin{tikzpicture}
 \foreach \a in {0,135,270} { \match{0,3}{\a:3} }
 \foreach \a in {0,-60,-120} { \match{0,0}{\a:3} }
 \foreach \a in {180,210,270} { \match{6,3}{\a:3} }
 \foreach \a in {150,180,-60,-120} { \match{6,0}{\a:3} }
\end{tikzpicture}

Cow

And this is the result if you remove the drop shadow from match style:

Without shadows

Update: fix for the shadows

In this question I learned a trick (credit to Andrew Stacey) to make the shadow to appear properly behind the matches. This is the final code, with a new example:

\documentclass{article}
\usepackage[margin=5mm,a4paper]{geometry}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,shadows,calc}

\pgfdeclarelayer{back}
\pgfsetlayers{back,main}

\makeatletter
\pgfkeys{%
  /tikz/on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  },
  /tikz/node on layer/.code={
    \pgfonlayer{#1}\begingroup
    \expandafter\def\expandafter\tikz@node@finish\expandafter{\expandafter\endgroup\expandafter\endpgfonlayer\tikz@node@finish}%
  },
}
\makeatother

\tikzset{
  match/.style = {
    cylinder,
    shape aspect = 1.5,
    cylinder uses custom fill,
    cylinder body fill=yellow,
    cylinder end fill = red,
    inner sep = 0pt,
    minimum width = 2mm,
    draw = black!20!yellow,
    sloped, midway,
    drop shadow = {shadow yshift=-.7mm, shadow xshift=1mm, opacity=.8, on layer=back},
  }
}
\def\match#1#2{
\path let
    \p1=(#2),
    \n1={0.8*veclen(\p1)}
    in (#1) -- +(#2)
    node[match,minimum height=\n1] {\phantom{x}};
}

\begin{document}
\begin{tikzpicture}
  \foreach \a in {0,60,...,359} { \match{0,0}{\a:3}; \match{\a:3}{\a+120:3} }
  \foreach \a in {0,120,...,359} { \match{\a:3}{\a-60:3} }
  \foreach \a in {60,180,...,359} { \match{\a:3}{\a+60:3} }
\end{tikzpicture}
\end{document}

Result:

Proper shadows

Update: hand-made matchstick figures

Sorry! I cannot stop tweaking! If you introduce a little random rotation in the match definition:

\def\match#1#2{
\path let
    \p1=(#2),
    \n1={0.8*veclen(\p1)}
    in (#1) -- +(#2)
    node[rotate=-5+10*rnd, match, minimum height=\n1] {\phantom{x}};
}

You get more interesting (IMHO) results:

Hand made

share|improve this answer

With PSTricks. Just 4 fun!

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\def\ms(#1)#2{%
    \rput{#2}(#1){%
        \psline[linewidth=6pt,linecolor=brown](3,0)
        \psellipse*[linecolor=red](3,0)(6pt,4pt)}
        \ignorespaces
}

\SpecialCoor
\begin{document}    
\multido{\i=0+30}{12}{%
\begin{pspicture}(-4,-4)(4,4)
    \ms(1;\i){\i}
\end{pspicture}}
\end{document}

enter image description here

share|improve this answer

A solution using PSTricks:

\documentclass{article}

\usepackage[
  figureposition = bottom
]{caption}
\usepackage{
  pstricks,
  multido
}

\psset{
  dimen = middel,
  fillstyle = solid
}
\def\stickHori(#1,#2){%
  \rput[lb](#1,#2){%
    \begin{pspicture}(1.8,0.15)
      \psline[linecolor = black!50, linewidth = 2\pslinewidth](0.2,0)(1.8,0)(1.8,0.15)
      \psframe[linestyle = none, fillcolor = yellow!70](0.2,0)(1.65,0.15)
      \psframe[linestyle = none, fillcolor = red!70](1.65,0)(1.8,0.15)
    \end{pspicture}%
  }%
}
\def\stickVert(#1,#2){%
  \rput[lb](#1,#2){%
    \begin{pspicture}(0.15,1.8)
      \psline[linecolor = black!50, linewidth = 2\pslinewidth](0,0.2)(0.15,0.2)(0.15,1.8)
      \psframe[linestyle = none, fillcolor = yellow!70](0,0.35)(0.15,1.8)
      \psframe[linestyle = none, fillcolor = red!70](0,0.2)(0.15,0.35)
    \end{pspicture}%
  }%
}

\begin{document}

\begin{figure}[htbp]
\centering
\begin{pspicture}(11.25,2)
  \multido{\rA = 0+1.85}{6}{%
    \stickHori(\rA,0)
    \stickHori(\rA,1.85)}
  \multido{\rB = 0+1.85}{7}{%
    \stickVert(\rB,0)}
\end{pspicture}
\caption{Stick figure.}
\label{fig:1}
\end{figure}

\end{document}

output1

Here are the different digital digits (with optional parameters):

\documentclass{article}

\usepackage{expl3}
\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

\newcommand*\SpaceTotal{\calc{\Width+\Space}}
\newcommand*\LengthTotal{\calc{\Length+\Width}}
\newcommand*\Bottom{\SpaceTotal}
\newcommand*\Middel{\calc{\LengthTotal+\SpaceTotal+\Space}}
\newcommand*\Top{\calc{\HeightTotal-\Width}}
\newcommand*\Lower{\SpaceTotal}
\newcommand*\Upper{\calc{\LengthTotal+2*\SpaceTotal+\Space}}
\newcommand*\Left{\SpaceTotal}
\newcommand*\Right{\calc{\LengthTotal+\SpaceTotal+\Space}}
\newcommand*\WidthTotal{\calc{\LengthTotal+2*\SpaceTotal}}
\newcommand*\HeightTotal{\calc{2*\LengthTotal+3*\SpaceTotal+\Space}}

\usepackage{pstricks}

\psset{
  dimen = middel,
  fillstyle = solid
}

\def\stickHori(#1,#2){%
  \rput[lb](#1,#2){%
    \begin{pspicture}(\LengthTotal,\Width)
      \psline[linecolor = black!50, linewidth = 2\pslinewidth]%
        (0,0)(\LengthTotal,0)(\LengthTotal,\Width)
      \psframe[linestyle = none, fillcolor = yellow!70]%
        (0,0)(\Length,\Width)
      \psframe[linestyle = none, fillcolor = red!70]%
        (\Length,0)(\LengthTotal,\Width)
    \end{pspicture}%
  }%
}
\def\stickVert(#1,#2){%
  \rput[lb](#1,#2){%
    \begin{pspicture}(\Width,\LengthTotal)
      \psline[linecolor = black!50, linewidth = 2\pslinewidth]%
        (0,0)(\Width,0)(\Width,\LengthTotal)
      \psframe[linestyle = none, fillcolor = yellow!70]%
        (0,\Width)(\Width,\LengthTotal)
      \psframe[linestyle = none, fillcolor = red!70]%
        (0,0)(\Width,\Width)
    \end{pspicture}%
  }%
}

\newcommand*\digitZero{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(0,\Lower)
    \stickVert(0,\Upper)
    \stickVert(\Right,\Lower)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitOne{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickVert(\Right,\Bottom)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitTwo{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Middel)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(0,\Lower)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitThree{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Middel)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(\Right,\Lower)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitFour{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,\Middel)
    \stickVert(0,\Upper)
    \stickVert(\Right,\Lower)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitFive{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Middel)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(0,\Upper)
    \stickVert(\Right,\Lower)
  \end{pspicture}%
}
\newcommand*\digitSix{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Middel)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(0,\Lower)
    \stickVert(0,\Upper)
    \stickVert(\Right,\Lower)
  \end{pspicture}%
}
\newcommand*\digitSeven{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(\Right,\Bottom)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitEight{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Middel)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(0,\Lower)
    \stickVert(0,\Upper)
    \stickVert(\Right,\Lower)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}
\newcommand*\digitNine{%
  \begin{pspicture}(\WidthTotal,\HeightTotal)
    \stickHori(\SpaceTotal,0)
    \stickHori(\SpaceTotal,\Middel)
    \stickHori(\SpaceTotal,\Top)
    \stickVert(0,\Upper)
    \stickVert(\Right,\Lower)
    \stickVert(\Right,\Upper)
  \end{pspicture}%
}

% parameters
\def\Length{1.3}
\def\Width{0.15}
\def\Space{0.05}


\begin{document}

\begin{center}
         \digitZero
  \qquad \digitOne
  \qquad \digitTwo
  \qquad \digitThree
  \qquad \digitFour
\end{center}
\begin{center}
         \digitFive
  \qquad \digitSix
  \qquad \digitSeven
  \qquad \digitEight
  \qquad \digitNine
\end{center}

\end{document}

output2

share|improve this answer

With new (TikZ 3.0) arrows.meta library it's easy to draw matches. You can create a special arrow tip or just adjust provided Ellipse one. This way you don't need to use decorations at all. Unfortunately you won't have shadows.

Just a little example:

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta}

\begin{document}
\begin{tikzpicture}[
    match/.style={line width=3pt,
                  yellow,
                  -{Ellipse[red, length=6pt, width'=0pt .5]},
                  shorten <=3pt, 
                  shorten >=3pt},
    every path/.style=match]
    \foreach \i [remember=\i as \lasti (initially {(135:2)})] in 
        {(0,0),(2,0),(4,0),(4,-2),(2,-2),(0,-2),(0,0)}
        \draw \lasti--\i;
    \draw (0,-2) -- ++(250:2); 
    \draw (0,-2) -- ++(290:2);
    \draw (4,-2) -- ++(250:2);
    \draw (4,-2) -- ++(290:2);
    \draw[-{Ellipse[blue, length=4pt, width=4pt]}] (4,0)  -- ++(340:2);
    \draw (4,-2) -- ++(45:2);
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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