# Reproduce fundamental cell in Tikzpicture

I would like to make easier the creation of the following diagram. I wrote this code that makes a so called dimer diagram where are different hexagons. Each hexagons is numbered and the plot just reproduce the red dashed parallelogram.

\documentclass[12pt]{article}
\usepackage{tikz}                       %immagini PGF
\usetikzlibrary{positioning,trees,decorations.pathmorphing,decorations.markings,decorations.pathreplacing,calc,shapes,patterns,arrows}
\usepackage{pgfplots}
%Proprietà tikzpicture
\newcommand*\circled[1]{\tikz[baseline=(char.base)]{
\node[shape=circle,draw,inner sep=2pt] (char) {#1};}}
\begin{document}
\begin{tikzpicture}
\node at (0:0cm) {$1$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\coordinate (1c) at (270:0.6cm);
\begin{scope}[xshift=1.5cm,yshift=0.87cm]
\node at (0:0cm) {$2$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[xshift=1.5cm,yshift=-0.87cm]
\node at (0:0cm) {$3$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[yshift=-1.74cm,xshift=0cm]
\node at (0:0cm) {$2$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[xshift=-1.5cm,yshift=-0.87cm]
\node at (0:0cm) {$3$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[xshift=-1.5cm,yshift=0.87cm]
\node at (0:0cm) {$2$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[yshift=1.74cm,xshift=0cm]
\node at (0:0cm) {$3$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[xshift=3cm,yshift=0cm]
\node at (0:0cm) {$1$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\coordinate (2c) at (270:0.6cm);
\end{scope}
\begin{scope}[xshift=3cm,yshift=-1.74cm]
\node at (0:0cm) {$2$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\begin{scope}[xshift=-1.5cm,yshift=-2.61cm]
\node at (0:0cm) {$1$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\coordinate (4c) at (270:0.6cm);
\end{scope}
\begin{scope}[xshift=1.5cm,yshift=-2.61cm]
\node at (0:0cm) {$1$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\coordinate (3c) at (270:0.6cm);
\end{scope}
\begin{scope}[yshift=-3.48cm,xshift=0cm]
\node at (0:0cm) {$3$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\end{scope}
\draw[dashed,thick,red] (1c)--(2c)--(3c)--(4c)--(1c);
\end{tikzpicture}

\end{document}


What I would like to know is if it is possible to write the code in some smart way so that I give the fundamental cell (the red dashed parallelogram) and then I can reproduce the graph over all the edges of this parallelogram. So if, for instance, I make a plot of only the parallelogram (that is a picture that can change), is it possible to copy the figure as it is and then paste it all around the parallelogram (or the kind of figure that the red dashed lines will form)?

• What's the rule from parallelogram to that lattice thing? – percusse Jul 23 '18 at 13:27
• Basically you have a surface with all these hexagons. The parallelogram contains the fundamental cell, which is the minimum surface that if reproduced you can obtain all the surface. There is no a precise rule, it needs just to contain all the necessary dots and lines inside so that if I copy the parallelogram joining the edges (basically left edges joined with the right edges of the parallelogram), you have all the surface. My question is in fact: if I have this parallelogram, or a figure, how can I copy and paste it all around the edges of the figure? – Alessandro Mininno Jul 23 '18 at 13:39
• So I am looking for a smart way to draw this kind of pictures. I know that the figure is reproduced by just copying and pasting the parallelogram, so if I save the parallelogram, how can I reproduce it in such a way that exactly the edge of a parallelogram coincide with the corresponding edge of another parallelogram. – Alessandro Mininno Jul 23 '18 at 13:42
• That sounds like Penrose tiling. We have a couple of questions here already – percusse Jul 23 '18 at 13:46

Here is a proposal. I am not sure I understand your question. But here come two codes. The first one demonstrates how to draw the lattice with less effort and the second one how to patch some fundamental cells together to a lattice using a \savebox.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes,calc}
\begin{document}
\tikzset{hexa/.style= {shape=regular polygon,regular polygon sides=6,
minimum height=2.3cm, %<-- you need only to adjust this value to rescale the lattice
draw,inner sep=0,anchor=south}}
% this is just a trick to measure some distances, not too important
\newsavebox\testhexa
\sbox\testhexa{\begin{tikzpicture}
\node[hexa] (test){};
\path let \p1=($(test.corner 1)-(test.corner 3)$),\p2=($(test.corner 1)-(test.corner 5)$)
in \pgfextra{\xdef\DeltaX{\x1}\xdef\DeltaY{\y2}};
\end{tikzpicture}}
% this is boundary of the fundamental cell
\newcommand{\FBoxPath}{-- ++(2*\DeltaX,0) -- ++(60:{2*\DeltaY*sin(60)})  -- ++
(-2*\DeltaX,0) -- cycle}
\section*{An arguably easier way to draw the lattice}

\begin{tikzpicture}
\foreach \X in {0,...,3}{%
\pgfmathsetmacro\Ymax{ifthenelse(\X==0,2,ifthenelse(\X==3,2,4-\X))}
\pgfmathsetmacro\Ymin{ifthenelse(\X==3,1,0)}
\foreach \Y in {\Ymin,...,\Ymax}{%
\pgfmathtruncatemacro{\Z}{mod(9+pow(-1,\X)*\Y,3)+1}
\node[hexa] (h\X;\Y) at ({\X*\DeltaX},{\Y*\DeltaY+pow(-1,\X)*\DeltaY/4}) {\Z};
\foreach \V in {1,...,6}
{\ifodd\V
\draw[fill=white] (h\X;\Y.corner \V) circle (4pt);
\else
\fill (h\X;\Y.corner \V) circle (4pt);
\fi
}}  }
\draw[red,dashed] (0,1) \FBoxPath ;
\end{tikzpicture}

\section*{Patching fundamental cells together to a new'' lattice}

% now define a savebox of the size of the fundamental cell
\newsavebox\FundamentalCell
\sbox\FundamentalCell{
\begin{tikzpicture}
\clip (0,1) \FBoxPath;
\foreach \X in {0,...,3}{%
\pgfmathsetmacro\Ymax{ifthenelse(\X==0,2,ifthenelse(\X==3,2,4-\X))}
\pgfmathsetmacro\Ymin{ifthenelse(\X==3,1,0)}
\foreach \Y in {\Ymin,...,\Ymax}{%
\pgfmathtruncatemacro{\Z}{mod(9+\Y+2*\X,3)+1}
\node[hexa] (h\X;\Y) at ({\X*\DeltaX},{\Y*\DeltaY+pow(-1,\X)*\DeltaY/4}) {\Z};
\foreach \V in {1,...,6}
{\ifodd\V
\draw[fill=white] (h\X;\Y.corner \V) circle (4pt);
\else
\fill (h\X;\Y.corner \V) circle (4pt);
\fi
}}  }
\end{tikzpicture}
}

\begin{tikzpicture}[scale=0.3,transform shape]
\foreach \X in {0,...,5}
{ \foreach \Y in {0,...,5}
{
\node at ($\X*(2*\DeltaX,0)+\Y*(60:{2*\DeltaY*sin(60)})$)
{\usebox{\FundamentalCell}};
}}

\end{tikzpicture}
\end{document}


• Actually you answered my question using that algorithm that compute the dimension of the hegaxon and then it stores the coordinates in \DeltaX and \DeltaY (am I understanding right?). I have defined my boxes with the fundamental cell and then I used the cycles and the coordinates in order to shift the box all around the picture. Thank you, this is what I was looking for. I will now understand how to find the coordinates in the case in which there are more complex or different shapes, but now I know that there is savebox that can help me. – Alessandro Mininno Jul 23 '18 at 15:37
• Glad to hear. (... and I labeled that bit "not too important" ;-) But yes, this is a rather easy way to extract distances and coordinates. – marmot Jul 23 '18 at 16:09

An option using your code but in structured mode, like defining functions.

RESULT:

MWE:

\documentclass[border=12pt]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\def\cell(#1)#2[#3]{% This draw one cell #1:position #2:cell content #3: Identifier
\begin{scope}[shift={(#1)}]
\node at (0:0cm) {$#2$};
\node[draw,circle,fill=black] (A) at (0:1cm) {};
\node[draw,circle] (B) at (60:1cm) {};
\node[draw,circle,fill=black] (C) at (120:1cm) {};
\node[draw,circle] (D) at (180:1cm) {};
\node[draw,circle,fill=black] (E) at (240:1cm) {};
\node[draw,circle] (F) at (300:1cm) {};
\draw[thick] (A) -- (B);
\draw[thick] (B) -- (C);
\draw[thick] (C) -- (D);
\draw[thick] (D) -- (E);
\draw[thick] (E) -- (F);
\draw[thick] (F) -- (A);
\coordinate (c#3) at (270:0.6cm);
\end{scope}
}
\def\cropcell(#1)#2{%This draw eight cells but croped whith the shape #1 Position #2 crop line style
\begin{scope}[shift={(#1)}]
\clip (1.5,-0.87-0.6)--(-1.5,-0.87-0.6)--(0,2*0.87-0.6)--(3,2*0.87-0.6)--cycle;
\draw[#2,line width=2pt] (1.5,-0.87-0.6)--(-1.5,-0.87-0.6)--(0,2*0.87-0.6)--(3,2*0.87-0.6)--cycle;
\cell(0,0){2}[1]
\cell(1.5,0.87){3}[2]
\cell(1.5,-0.87){1}[3]
\cell(-1.5,-0.87){1}[4]
\cell(0,-2*0.87){3}[5]
\cell(0,2*0.87){1}[6]
\cell(3,2*0.87){1}[7]
\cell(3,0){2}[8]
\end{scope}
}

% Start drawing the thing...

\cell(-4,5){9}[8]
\draw node [anchor=west] at (-5,6.5) {Using definition \verb+\cell(-4,5){9}[8]+};
\cropcell(3,5){red}
\draw node [anchor=west] at (1.5,6.5) {Using definition \verb+\cropcell(3,5){red}+};

\clip[draw] (-5,-3) rectangle (7,3);
\cropcell(0,0){draw,red,dashed}
\foreach \x/\y in {
-3/3,-1/3,1/3,3/3,5/3,
-4/0,-2/0,2/0,4/0,
-5/-3,-3/-3,-1/-3,1/-3,3/-3}{
\cropcell(\x*1.5,\y*0.87){draw=none}
}

\end{tikzpicture}

\end{document}

• I will consider also your option, but it seems to me too much ad hoc. Obviously, it can be generalized but it takes a lot of time to find all the positions everytime, and this reason was the main reason why I chose to ask a question on Stack Exchange. Thank you – Alessandro Mininno Jul 23 '18 at 15:55

Here's a version drawn with Metapost.

I made it a bit simpler by centering the base cell on the origin, so that I could draw the hexagon and the arms in simple loops.

\documentclass[border=5mm]{standalone}
\usepackage{luatex85}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
% unit size
numeric u;
u = 1cm;

% the basic cell to repeat
picture cell;
cell = image(
draw for i=0 upto 5: (u,0) rotated 60i -- endfor cycle;
for i=0 upto 5:
draw ((u,0)--(3/2u,0)) rotated 60i;
fill fullcircle scaled 7 shifted ((u,0) rotated 60i) withcolor if odd i: white else: 2/3 blue fi;
draw fullcircle scaled 7 shifted ((u,0) rotated 60i);
endfor;
label("$1$", origin);
label("$2$", (sqrt(3)*u,0) rotated 30);
label("$3$", (sqrt(3)*u,0) rotated 210);
);

% draw round where the central cell will be
draw unitsquare shifted -(1/2, 1/2)
xscaled 3u
yscaled (3*sqrt(3)/2*u)
slanted (1/sqrt(3))
dashed evenly
withcolor 3/4 red;

% define two unit vectors...
pair i, j;
i = 3u * right;
j = i rotated 60;

% draw the cell shifted by x and y times the unit vectors
numeric n;
n = 2;
for x=-n upto n:
for y=-n upto n:
draw cell shifted (x*i + y*j);
endfor
endfor
endfig;
\end{mplibcode}
\end{document}


This is wrapped up in luamplib so you need to compile it with lualatex or work out how to adapt it for plain Metapost