[Tex/LaTex] Join the dots – Hannukah

funtikz-pgf

The festive season is upon us and we all of course bring out our favourite TikZ Hannukah Menorahs to celebrate. However, our children are still not satisfied and demand an activity to do during the long dark evenings. Although we attempt to provide them with downloaded join-the-dots puzzles, they immediately recognise when it has not been made in TikZ.

Can we rescue the situation by providing colourful join-the-dots Hannukah Menorahs (or even dreidels) to while away the time?

Here is an uncolourful example of a Chanukiah (well … a menorah really as it has the wrong number of candles for Hannukah which should have eight plus one).

enter image description here

And here is an uncolourful example of a dreidel.

enter image description here

Best Answer

Ok, with a modicum of color, here is a join the dots decoration:

\documentclass[border=0.125cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\makeatletter
\newcount\tikzjointhedotsnumber


\pgfdeclaredecoration{join the dots}{initial}{%
  \state{initial}[width=0pt, next state=do dots, persistent precomputation={\global\tikzjointhedotsnumber=1}]{}
  %
  \state{do dots}[width=\pgfdecoratedinputsegmentlength, persistent postcomputation={\global\advance\tikzjointhedotsnumber by1}]{%
    \pgfcoordinate{@dot-\the\tikzjointhedotsnumber}{\pgfpointorigin}%
  }
  %
  \state{final}{%
    % Is the last point the same as the first?
      \pgfpointdiff{\pgfpointdecoratedpathlast}{\pgfpointdecoratedpathfirst}%
      \pgfmathveclen{\the\pgf@x}{\the\pgf@y}%
      \ifdim\pgfmathresult pt=0pt\relax%
        \global\advance\tikzjointhedotsnumber by-1\relax
      \else
        \pgftransformshift{\pgfpointdecoratedpathlast}%
        \pgfcoordinate{@dot-\the\tikzjointhedotsnumber}{\pgfpointorigin}%
      \fi
      % Ok, now we do everything. Draw the dots and place the numbers.
      %
      \c@pgf@counta=\tikzjointhedotsnumber%
      \c@pgf@countb=2\relax%
      \edef\lastdot{\the\tikzjointhedotsnumber}%
      \def\nextdot{2}%
      \pgftransformreset%
      \pgfmathloop%
      \ifnum\pgfmathcounter>\tikzjointhedotsnumber
      \else%
        % Draw the dot.
        \edef\tmp{\the\tikzjointhedotsnumber}%
                \tikzjointhedotsnumber=\pgfmathcounter\relax%
        \path [shift={(@dot-\pgfmathcounter)}, every dot/.try, dot \pgfmathcounter/.try]; 
         \tikzjointhedotsnumber=\tmp% 
        %
        % Calculate the dot number node anchor
        \pgfmathanglebetweenpoints{\pgfpointanchor{@dot-\pgfmathcounter}{center}}{\pgfpointanchor{@dot-\the\c@pgf@counta}{center}}%
        \pgf@xc=\pgfmathresult pt\relax%
        \ifdim0pt>\pgf@xc%
          \advance\pgf@xc by360pt\relax%
        \fi%
        \pgfmathanglebetweenpoints{\pgfpointanchor{@dot-\pgfmathcounter}{center}}{\pgfpointanchor{@dot-\the\c@pgf@countb}{center}}%
        \pgf@yc=\pgfmathresult pt\relax%
        \ifdim0pt>\pgf@yc%
          \advance\pgf@yc by360pt\relax%
        \fi%
        \ifdim\pgf@xc>\pgf@yc%
          \pgf@x=360pt\relax%
        \else%
          \pgf@x=0pt\relax%
        \fi%
        \advance\pgf@x by-\pgf@xc%
        \advance\pgf@x by\pgf@yc%
        \divide\pgf@x by2\relax%
        \advance\pgf@x by\pgf@xc%
        \advance\pgf@x by180pt\relax%
        \edef\dotnumberanchor{\the\pgf@x}%
        \node [anchor=\dotnumberanchor, every dot number/.try, dot number \pgfmathcounter/.try] 
          at (@dot-\pgfmathcounter)
          {\tikzjointhedotsnumber=\pgfmathcounter\relax\tikzjointhedotstypesetnumber{\tikzjointhedotsnumber}};
        \c@pgf@counta=\pgfmathcounter\relax%
            \advance\c@pgf@countb by1\relax%
            \ifnum\c@pgf@countb>\tikzjointhedotsnumber%
              \c@pgf@countb=1\relax%
            \fi%
        \repeatpgfmathloop%
  }
}

% Command for typesetting dot number
% #1 - a count register holding the current dot number
%
\def\tikzjointhedotstypesetnumber#1{\the#1}
\makeatletter
% Keys for setting dot number styles
\tikzset{%
  syle dot number range/.code args={#1 to #2 with #3}{%
    \c@pgf@counta=#1
    \pgfmathloop
    \ifnum\c@pgf@counta>#2\relax%
    \else%
      \tikzset{dot number \the\c@pgf@counta/.style={#3}}%
      \advance\c@pgf@counta by1
    \repeatpgfmathloop%
  },
    style dot number list/.code args={#1 with #2}{%
      \pgfutil@for\tmp:=#1\do{%
        \tikzset{dot number \tmp/.style={#2}}%
      }%
    }
}
\makeatother

\tikzset{%
  % Executed for every dot
  every dot/.style={fill=black,
    insert path={  circle [radius=.75mm] coordinate [alias=dot-last] (dot-\the\tikzjointhedotsnumber)  }
  },
  % Executed for every dot number
  every dot number/.style={
   shape=circle,
   font=\footnotesize\sf,
  },
  join the dots/.style={
    decoration=join the dots, decorate
  },
  lines/.style={
    ultra thick,
    line join=round,
    line cap=round
  },
  crayon/.style={
    draw=#1,
    line join=round,
    line cap=round,
    line width=1mm
  },
  sketch/.style={
    bend right, out=rand*10, in=180-rand*10
  }
}

\begin{document}
\begin{tikzpicture}
% Draw and number the dots
\path [postaction={join the dots}]
    (-1/2,11) 
    \foreach \a [count=\c from 1, evaluate={\d=\a+1;\s=90/\d;}] in {1,2,3,4}{
        -- ++(0,{\a==1?-2:-1})
        \foreach \i in {1,...,\d}{
            arc (270-\i*\s+\s:270-\i*\s:\a*2-1 and \a*3/2-1/2) 
        }
        -- ++(-1,0) coordinate [midway] (candle-\c)
        \foreach \i in {1,...,\d}{
            arc (180+\i*\s-\s:180+\i*\s:\a*2 and \a*3/2) 
        }
    }
    -- ++(0,-1) 
    -| ++(-1,-1/2) -| ++(-1,-1/2) -| ++(-1,-1/2)
    -- ++(7,0)
    |- ++(-1,1/2) |- ++(-1,1/2) |- ++(-1,1/2)
    \foreach \a [count=\c from 5, evaluate={\d=\a+1;\s=90/\d;}] in {4,3,2,1}{
        -- ++(0,1)
        \foreach \i in {1,...,\d}{
            arc (270+\i*\s-\s:270+\i*\s:\a*2 and \a*3/2) 
        }
        -- ++(-1,0) coordinate [midway] (candle-\c)
        \foreach \i in {1,...,\d}{
            arc (360-\i*\s+\s:360-\i*\s:\a*2-1 and \a*3/2-1/2) 
        }
    }
    -- ++(0,2);
% Draw the lines that are visible.
\draw [lines] 
  (dot-1)  -- (dot-last) coordinate [midway] (candle-9);

% Draw candles
\foreach \cn in {1,...,9}{% 
 \tikzset{shift=(candle-\cn), yshift=1pt}%
 % Candle
 \fill [lines, fill=purple!80, rounded corners=0.125cm]
  (-1/3,0) to [sketch] (-1/3,3) -- (1/3,3)  to [sketch] (1/3,0);
 % Wick
 \draw [lines] (0,3) -- ++(0,1/4);
 \tikzset{shift={(0,3+1/8)}, xscale=round(rnd)*2-1,yscale=1+rand/8}
 \foreach \s/\c in {1/yellow,.5/red}
 \path [lines, fill=\c!50!orange, opacity=3/4, scale=\s] 
   (0,0) 
   arc (270:180:3/8) 
   .. controls ++(0,1/4) and ++(0,-1/4) .. (0,3/2)
   arc (90:0:3/8 and 1) arc (360:270:3/8 and 1/2);
} 
\end{tikzpicture}%

\end{document}

enter image description here

And this will take a long time to compile.

\documentclass[border=0.125cm]{standalone}
\standaloneenv{minipage}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\makeatletter
\newcount\tikzjointhedotsnumber


\pgfdeclaredecoration{join the dots}{initial}{%
  \state{initial}[width=0pt, next state=do dots, persistent precomputation={\global\tikzjointhedotsnumber=1}]{}
  %
  \state{do dots}[width=\pgfdecoratedinputsegmentlength, persistent postcomputation={\global\advance\tikzjointhedotsnumber by1}]{%
    \pgfcoordinate{@dot-\the\tikzjointhedotsnumber}{\pgfpointorigin}%
  }
  %
  \state{final}{%
    % Is the last point the same as the first?
      \pgfpointdiff{\pgfpointdecoratedpathlast}{\pgfpointdecoratedpathfirst}%
      \pgfmathveclen{\the\pgf@x}{\the\pgf@y}%
      \ifdim\pgfmathresult pt=0pt\relax%
        \global\advance\tikzjointhedotsnumber by-1\relax
      \else
        \pgftransformshift{\pgfpointdecoratedpathlast}%
        \pgfcoordinate{@dot-\the\tikzjointhedotsnumber}{\pgfpointorigin}%
      \fi
      % Ok, now we do everything. Draw the dots and place the numbers.
      %
      \c@pgf@counta=\tikzjointhedotsnumber%
      \c@pgf@countb=2\relax%
      \edef\lastdot{\the\tikzjointhedotsnumber}%
      \def\nextdot{2}%
      \pgftransformreset%
      \pgfmathloop%
      \ifnum\pgfmathcounter>\tikzjointhedotsnumber
      \else%
        % Draw the dot.
        \edef\tmp{\the\tikzjointhedotsnumber}%
                \tikzjointhedotsnumber=\pgfmathcounter\relax%
        \path [shift={(@dot-\pgfmathcounter)}, every dot/.try, dot \pgfmathcounter/.try]; 
         \tikzjointhedotsnumber=\tmp% 
        %
        % Calculate the dot number node anchor
        \pgfmathanglebetweenpoints{\pgfpointanchor{@dot-\pgfmathcounter}{center}}{\pgfpointanchor{@dot-\the\c@pgf@counta}{center}}%
        \pgf@xc=\pgfmathresult pt\relax%
        \ifdim0pt>\pgf@xc%
          \advance\pgf@xc by360pt\relax%
        \fi%
        \pgfmathanglebetweenpoints{\pgfpointanchor{@dot-\pgfmathcounter}{center}}{\pgfpointanchor{@dot-\the\c@pgf@countb}{center}}%
        \pgf@yc=\pgfmathresult pt\relax%
        \ifdim0pt>\pgf@yc%
          \advance\pgf@yc by360pt\relax%
        \fi%
        \ifdim\pgf@xc>\pgf@yc%
          \pgf@x=360pt\relax%
        \else%
          \pgf@x=0pt\relax%
        \fi%
        \advance\pgf@x by-\pgf@xc%
        \advance\pgf@x by\pgf@yc%
        \divide\pgf@x by2\relax%
        \advance\pgf@x by\pgf@xc%
        \advance\pgf@x by180pt\relax%
        \edef\dotnumberanchor{\the\pgf@x}%
        \node [anchor=\dotnumberanchor, every dot number/.try, dot number \pgfmathcounter/.try] 
          at (@dot-\pgfmathcounter)
          {\tikzjointhedotsnumber=\pgfmathcounter\relax\tikzjointhedotstypesetnumber{\tikzjointhedotsnumber}};
        \c@pgf@counta=\pgfmathcounter\relax%
            \advance\c@pgf@countb by1\relax%
            \ifnum\c@pgf@countb>\tikzjointhedotsnumber%
              \c@pgf@countb=1\relax%
            \fi%
        \repeatpgfmathloop%
  }
}

% Command for typesetting dot number
% #1 - a count register holding the current dot number
%
\def\tikzjointhedotstypesetnumber#1{\the#1}
\makeatletter
% Keys for setting dot number styles
\tikzset{%
  syle dot number range/.code args={#1 to #2 with #3}{%
    \c@pgf@counta=#1
    \pgfmathloop
    \ifnum\c@pgf@counta>#2\relax%
    \else%
      \tikzset{dot number \the\c@pgf@counta/.style={#3}}%
      \advance\c@pgf@counta by1
    \repeatpgfmathloop%
  },
  style dot number list/.code args={#1 with #2}{%
    \pgfutil@for\tmp:=#1\do{%
      \tikzset{dot number \tmp/.style={#2}}%
    }%
  }
}
\makeatother

\tikzset{%
  % Executed for every dot
  every dot/.style={fill=black,
    insert path={  circle [radius=.75mm] coordinate [alias=dot-last] (dot-\the\tikzjointhedotsnumber)  }
  },
  % Executed for every dot number
  every dot number/.style={
   shape=circle,
   font=\footnotesize\sf,
  },
  join the dots/.style={
    decoration=join the dots, decorate
  },
  lines/.style={
    ultra thick,
    line join=round,
    line cap=round
  },
  crayon/.style={
    draw=#1,
    line join=round,
    line cap=round,
    line width=1mm
  },
  sketch/.style={
    bend right, out=rand*10, in=180-rand*10
  }
}

\begin{document}
% Put (most of) the picture in a box, so it doesn't
% have to be redrawn every iteration.
\newbox\hanukkahbox
\setbox\hanukkahbox=\hbox{%
\begin{tikzpicture}[baseline={(0,0)}]
% Draw and number the dots
\path [postaction={join the dots}]
    (-1/2,11) 
    \foreach \a [count=\c from 1, evaluate={\d=\a+1;\s=90/\d;}] in {1,2,3,4}{
        -- ++(0,{\a==1?-2:-1})
        \foreach \i in {1,...,\d}{
            arc (270-\i*\s+\s:270-\i*\s:\a*2-1 and \a*3/2-1/2) 
        }
        -- ++(-1,0) coordinate [midway] (candle-\c)
        \foreach \i in {1,...,\d}{
            arc (180+\i*\s-\s:180+\i*\s:\a*2 and \a*3/2) 
        }
    }
    -- ++(0,-1) 
    -| ++(-1,-1/2) -| ++(-1,-1/2) -| ++(-1,-1/2)
    -- ++(7,0)
    |- ++(-1,1/2) |- ++(-1,1/2) |- ++(-1,1/2)
    \foreach \a [count=\c from 5, evaluate={\d=\a+1;\s=90/\d;}] in {4,3,2,1}{
        -- ++(0,1)
        \foreach \i in {1,...,\d}{
            arc (270+\i*\s-\s:270+\i*\s:\a*2 and \a*3/2) 
        }
        -- ++(-1,0) coordinate [midway] (candle-\c)
        \foreach \i in {1,...,\d}{
            arc (360-\i*\s+\s:360-\i*\s:\a*2-1 and \a*3/2-1/2) 
        }
    }
    -- ++(0,2);
% Draw the lines that are visible.
\draw [lines] 
  (dot-1)  -- (dot-last) coordinate [midway] (candle-9);
\end{tikzpicture}}%
%
\foreach \k in {1,...,88}{%
\begin{minipage}{\wd\hanukkahbox}%
\begin{tikzpicture}
% Place the picture box.
\pgftext[bottom]{\copy\hanukkahbox}%
% Draw candles
\foreach \cn in {1,...,9}{% 
 \tikzset{shift=(candle-\cn), yshift=1pt}
 % Set the random seed as fixed with the candle number as
 % a parameter so that candles are different from each
 % other, but drawn the same on each outer iteration.
 \pgfmathsetseed{99+\cn*50}%
 % Candle
 \fill [lines, fill=purple!80, rounded corners=0.125cm]
  (-1/3,0) to [sketch] (-1/3,3) -- (1/3,3)  to [sketch] (1/3,0);
 % Wick
 \draw [lines] (0,3) -- ++(0,1/4);
 % Ensure highest point for bounding box
 \path (candle-9) -- ++(0,5);
 \pgfmathsetseed{99+\k*50+\cn*25}%
 \tikzset{shift={(0,3+1/8)}, xscale=round(rnd)*2-1,yscale=1+rand/8}
 \foreach \s/\c in {1/yellow,.5/red}
 \path [lines, fill=\c!50!orange, opacity=3/4, scale=\s] 
   (0,0) 
   arc (270:180:3/8) 
   .. controls ++(0,1/4) and ++(0,-1/4) .. (0,3/2)
   arc (90:0:3/8 and 1) arc (360:270:3/8 and 1/2);
} 
\pgfmathsetseed{99}%
\draw [crayon=black!80] (dot-1) \foreach \l in {1,...,\k}{ to [sketch] (dot-\l) };
\end{tikzpicture}%
\end{minipage}}

\end{document}

By using the animation features of gimp the pdf can be converted to a gif:

enter image description here

Finally, here is a dreidel:

\documentclass[tikz,border=0.125cm]{standalone}
\newcount\TeXXeTstate% <- Why?
\usepackage{cjhebrew}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\makeatletter
\newcount\tikzjointhedotsnumber


\pgfdeclaredecoration{join the dots}{initial}{%
  \state{initial}[width=0pt, next state=do dots, persistent precomputation={\global\tikzjointhedotsnumber=1}]{}
  %
  \state{do dots}[width=\pgfdecoratedinputsegmentlength, persistent postcomputation={\global\advance\tikzjointhedotsnumber by1}]{%
    \pgfcoordinate{@dot-\the\tikzjointhedotsnumber}{\pgfpointorigin}%
  }
  %
  \state{final}{%
    % Is the last point the same as the first?
      \pgfpointdiff{\pgfpointdecoratedpathlast}{\pgfpointdecoratedpathfirst}%
      \pgfmathveclen{\the\pgf@x}{\the\pgf@y}%
      \ifdim\pgfmathresult pt=0pt\relax%
        \global\advance\tikzjointhedotsnumber by-1\relax
      \else
        \pgftransformshift{\pgfpointdecoratedpathlast}%
        \pgfcoordinate{@dot-\the\tikzjointhedotsnumber}{\pgfpointorigin}%
      \fi
      % Ok, now we do everything. Draw the dots and place the numbers.
      %
      \c@pgf@counta=\tikzjointhedotsnumber%
      \c@pgf@countb=2\relax%
      \edef\lastdot{\the\tikzjointhedotsnumber}%
      \def\nextdot{2}%
      \pgftransformreset%
      \pgfmathloop%
      \ifnum\pgfmathcounter>\tikzjointhedotsnumber
      \else%
        % Draw the dot.
        \edef\tmp{\the\tikzjointhedotsnumber}%
                \tikzjointhedotsnumber=\pgfmathcounter\relax%
        \path [shift={(@dot-\pgfmathcounter)}, every dot/.try, dot \pgfmathcounter/.try]; 
         \tikzjointhedotsnumber=\tmp% 
        %
        % Calculate the dot number node anchor
        \pgfmathanglebetweenpoints{\pgfpointanchor{@dot-\pgfmathcounter}{center}}{\pgfpointanchor{@dot-\the\c@pgf@counta}{center}}%
        \pgf@xc=\pgfmathresult pt\relax%
        \ifdim0pt>\pgf@xc%
          \advance\pgf@xc by360pt\relax%
        \fi%
        \pgfmathanglebetweenpoints{\pgfpointanchor{@dot-\pgfmathcounter}{center}}{\pgfpointanchor{@dot-\the\c@pgf@countb}{center}}%
        \pgf@yc=\pgfmathresult pt\relax%
        \ifdim0pt>\pgf@yc%
          \advance\pgf@yc by360pt\relax%
        \fi%
        \ifdim\pgf@xc>\pgf@yc%
          \pgf@x=360pt\relax%
        \else%
          \pgf@x=0pt\relax%
        \fi%
        \advance\pgf@x by-\pgf@xc%
        \advance\pgf@x by\pgf@yc%
        \divide\pgf@x by2\relax%
        \advance\pgf@x by\pgf@xc%
        \advance\pgf@x by180pt\relax%
        \edef\dotnumberanchor{\the\pgf@x}%
        \node [anchor=\dotnumberanchor, every dot number/.try, dot number \pgfmathcounter/.try] 
          at (@dot-\pgfmathcounter)
          {\tikzjointhedotsnumber=\pgfmathcounter\relax\tikzjointhedotstypesetnumber{\tikzjointhedotsnumber}};
        \c@pgf@counta=\pgfmathcounter\relax%
            \advance\c@pgf@countb by1\relax%
            \ifnum\c@pgf@countb>\tikzjointhedotsnumber%
              \c@pgf@countb=1\relax%
            \fi%
        \repeatpgfmathloop%
  }
}

% Command for typesetting dot number
% #1 - a count register holding the current dot number
%
\def\tikzjointhedotstypesetnumber#1{\the#1}
\makeatletter
% Keys for setting dot number styles
\tikzset{%
  syle dot number range/.code args={#1 to #2 with #3}{%
    \c@pgf@counta=#1
    \pgfmathloop
    \ifnum\c@pgf@counta>#2\relax%
    \else%
      \tikzset{dot number \the\c@pgf@counta/.style={#3}}%
      \advance\c@pgf@counta by1
    \repeatpgfmathloop%
  },
    style dot number list/.code args={#1 with #2}{%
      \pgfutil@for\tmp:=#1\do{%
        \tikzset{dot number \tmp/.style={#2}}%
      }%
    }
}
\makeatother

\tikzset{%
  % Executed for every dot
  every dot/.style={fill=black,
    insert path={  circle [radius=.75mm] coordinate [alias=dot-last] (dot-\the\tikzjointhedotsnumber)  }
  },
  % Executed for every dot number
  every dot number/.style={
   font=\footnotesize\sf,
   anchor=\pgfdecoratedangle-90
  },
  join the dots/.style={
    decoration=join the dots, decorate
  },
  lines/.style={
    ultra thick,
    line join=round,
    line cap=round
  },
  style dot number list={15,16,17 with anchor=0},
}

\def\tikzjointhedotstypesetnumber#1{%
  \textcjheb{\ifcase#1\or'\or b\or g\or d\or h\or w\or z\or.h\or.t\or y\or k|%
    \or l\or m|\or n|\or s\or `\or p|\or.s|\or q\or r\or/s\or t\else?\fi}}
\begin{document}

\begin{tikzpicture}[x=(-40:0.5cm), y=(195:0.5cm), z=(75:0.5cm)]
\draw [lines] (1*cos 45,-1*sin 45,7) -- (1*cos 45,-1*sin 45,3) arc (-45:135:1) -- (-1*cos 45,1*sin 45,5.25);
\path[postaction=join the dots] 
  (1*cos 45,-1*sin 45,5.25) -- (3,-3, 3) -- (3,0,3) -- (3,3,3)
  -- (3,3,1) -- (3,3,-1) -- (3,3,-3) -- (3,0,-3) -- (3,-3,-3)
  -- (2,-2,-5) -- (1,-1,-7) -- (0,0,-9)
  -- (-1,1,-7) -- (-2,2,-5) -- (-3,3,-3)
  -- (-3,3,0) -- (-3,3,3)  -- (-1*cos 45,1*sin 45,5.25) -- (-1*cos 45,1*sin 45,7)
  -- (-1*cos 45,1*sin 45,9) -- (1*cos 45,-1*sin 45,9) -- (1*cos 45,-1*sin 45,7);

\node [yslant=-cos 40, scale=8, text=blue!50!purple] at (0,3,0) {\textcjheb{h}};
\node [yslant=cos 75, scale=8, text=red!50!orange] at (3,0,0) {\textcjheb{n|}};

\draw [lines]
  (dot-4) -- (dot-17)
  (dot-2) -- (dot-9)
  (dot-7) -- (dot-15);

\end{tikzpicture}
\end{document}

enter image description here