6

I would like to reproduce the hexagonal lattice using Tikz/PSTricks or a similar package in LaTex as shown in the images below.

There're already kinds of answers available here. However, all of them use for-loops whereas I wanted to create the hexagon's arrangement in a more controlled way, i.e. using the Cartesian x,y coordinates one by one.

Is it possible to create in that way, at least first two rows of the lattice?

enter image description here

I am adding a code for a single hexagon below (this needs to be modified as the lattice points are not placed correctly). Can this structure be repeated ensuring that the top leftmost coordinate is (-1,0) and the sides are of unit length?

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,decorations.markings}

\begin{document}

%% Create a hexagon:
\begin{tikzpicture}
 % For a hexagons the coordinates for the vertices in a sequence:
 %  (-1,0), (-1/2,sqrt{3}/2), (1/2,sqrt{3}/2), (1,0), (1/2,-sqrt{3}/2), (-1/2,-sqrt{3}/2)
 % sqrt{3}/2 = 0.866 (approx)   
 \draw [*-, color=red] (-1,0) --  (-0.5,0.866);
 \draw [*-, color=red] (-0.5,0.866) -- (0.5,0.866);
 \draw [*-, color=red] (0.5,0.866) -- (1,0);
 \draw [*-, color=red] (1,0) -- (0.5,-0.866);
 \draw [*-, color=red] (0.5,-0.866) -- (-0.5,-0.866);
 \draw [*-, color=red] (-0.5,-0.866) -- (-1,0);
\end{tikzpicture}

\end{document}

Following your suggestion, I have modified this a bit. I want to display the coordinates of one full hexagon:

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,decorations.markings}

\begin{document}

\begin{tikzpicture}
  \draw [color=red,mark=*] plot[samples at={-180,-120,...,180},variable=\x] 
  (\x:1);
  \node[color=black, left] at (-1,0) {\small (-1,0)};
  \node[color=black, left] at  (-0.5,0.866) {\small (-0.5,0.866)};
  \node[color=black, left] at  (-0.5,-0.866) {\small (-0.5,-0.866)};
  \node[color=black, right] at (1,0) {\small (1,0)};
  \node[color=black, right] at  (0.5,0.866) {\small (0.5,0.866)};
  \node[color=black, right] at  (0.5,-0.866) {\small (0.5,-0.866)};
\end{tikzpicture}


\end{document}

Output:

enter image description here

Can I do that after constructing the entire lattice?

  • Could you please explain what you mean by "one by one"? – Schrödinger's cat Oct 26 '19 at 1:29
  • What have you tried? Just don't use a loop if you want to take the scenic route. The patterns are identical modulo rotational symmetry, aren't they? – cfr Oct 26 '19 at 1:32
  • I wanted to keep (x,y) coordinates so that I can select some special points and annotate them later. That's what I meant by "one by one". I have modified my question with an example. Also, suppose I manage to create a hexagonal lattice from the examples below. Can I ensure my top left coordinate starts from (x,y)=(-1,0)? – hbaromega Oct 26 '19 at 11:12
  • You example can be shortened to \documentclass[tikz,border=3mm]{standalone} \begin{document} \begin{tikzpicture} \draw [color=red,mark=*] plot[samples at={-180,-120,...,180},variable=\x] (\x:1); \end{tikzpicture} \end{document}. I am, however, still not sure I understand the question. In my example below you can say \draw[pattern={hexa with circles[size=10pt,line width=.8pt,angle=90]}, pattern color=blue] (-1,0) rectangle ++(2,-2); , then the top left coordinate is a (-1,0). – Schrödinger's cat Oct 26 '19 at 14:46
  • Are you sure you have \tikzdeclarepattern{name=hexa with circles, ... in the code that you compile? – Schrödinger's cat Oct 26 '19 at 19:11
8

Let me mention that your code can be simplified to

\documentclass[tikz,border=3mm]{standalone}
\begin{document}
\begin{tikzpicture}
  \draw [color=red,mark=*] plot[samples at={-180,-120,...,180},variable=\x] 
  (\x:1);
\end{tikzpicture}
\end{document}

enter image description here

As you can see, this solves the problem of the misaligned circles (which come from the fact that you are adding them via arrow heads; you could fix the problem by shortening the paths, but I feel this is simpler).

The problem is that this contains hard coded distances and so on. Luckily the patterns.meta library has found its way to the manual recently, and this allows us to avoid that problem. As @cfr points out, you only need one of them since they are related by rotation, and patterns created with patterns.meta are rotatable, and you can adjust other parameters which are taken to be the line width and size (and you can dial the color, of course).

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{patterns.meta} 
\begin{document}
\tikzdeclarepattern{name=hexa,
  parameters={
      \pgfkeysvalueof{/pgf/pattern keys/size},
      \pgfkeysvalueof{/pgf/pattern keys/angle},
      \pgfkeysvalueof{/pgf/pattern keys/line width},
  },
  bounding box={(-.1pt,-.1pt) and
    (1.5*\pgfkeysvalueof{/pgf/pattern keys/size}+.1pt,
     {sin(60)*\pgfkeysvalueof{/pgf/pattern keys/size}+.1pt})},
  tile size={(1.5*\pgfkeysvalueof{/pgf/pattern keys/size},
              {sin(60)*\pgfkeysvalueof{/pgf/pattern keys/size}})},
  tile transformation={rotate=\pgfkeysvalueof{/pgf/pattern keys/angle}},
  defaults={
    size/.initial=5pt,
    angle/.initial=0,
    line width/.initial=.4pt,
}, code={
\draw[line width=\pgfkeysvalueof{/pgf/pattern keys/line width}] 
(0,{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2}) 
-- ({\pgfkeysvalueof{/pgf/pattern keys/size}*1/4},0) 
-- ({\pgfkeysvalueof{/pgf/pattern keys/size}*3/4},0)
-- (\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2})
(0.75*\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)})
-- (\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2})
 -- (1.5*\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2})
-- (1.75*\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)})
;
} }
\begin{tikzpicture}
\draw[pattern={hexa[size=10pt,line width=.8pt,angle=90]},
pattern color=blue] (0,0) rectangle ++(2,2); 
\draw[pattern={hexa[size=10pt,line width=.8pt,angle=0]},
pattern color=red] (3,0) rectangle ++(2,2); 
\end{tikzpicture}
\end{document}

enter image description here

Or with circles:

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{patterns.meta} 
\begin{document}
\tikzdeclarepattern{name=hexa with circles,
  parameters={
      \pgfkeysvalueof{/pgf/pattern keys/size},
      \pgfkeysvalueof{/pgf/pattern keys/angle},
      \pgfkeysvalueof{/pgf/pattern keys/line width},
      \pgfkeysvalueof{/pgf/pattern keys/radius},
  },
  bounding box={(-.1pt,-.1pt) and
    (1.5*\pgfkeysvalueof{/pgf/pattern keys/size}+.1pt,
     {sin(60)*\pgfkeysvalueof{/pgf/pattern keys/size}+.1pt})},
  tile size={(1.5*\pgfkeysvalueof{/pgf/pattern keys/size},
              {sin(60)*\pgfkeysvalueof{/pgf/pattern keys/size}})},
  tile transformation={rotate=\pgfkeysvalueof{/pgf/pattern keys/angle}},
  defaults={
    size/.initial=5pt,
    angle/.initial=0,
    line width/.initial=.4pt,
    radius/.initial=1.2pt,
}, code={
\draw[line width=\pgfkeysvalueof{/pgf/pattern keys/line width}] 
(0,{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2}) 
-- ({\pgfkeysvalueof{/pgf/pattern keys/size}*1/4},0) 
-- ({\pgfkeysvalueof{/pgf/pattern keys/size}*3/4},0)
-- (\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2})
(0.75*\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)})
-- (\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2})
 -- (1.5*\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2})
-- (1.75*\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)});
\fill 
(0,{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2}) circle[radius=\pgfkeysvalueof{/pgf/pattern keys/radius}]
({\pgfkeysvalueof{/pgf/pattern keys/size}*1/4},0) circle[radius=\pgfkeysvalueof{/pgf/pattern keys/radius}]
({\pgfkeysvalueof{/pgf/pattern keys/size}*3/4},0) circle[radius=\pgfkeysvalueof{/pgf/pattern keys/radius}]
(\pgfkeysvalueof{/pgf/pattern keys/size},{\pgfkeysvalueof{/pgf/pattern keys/size}*sin(60)/2}) circle[radius=\pgfkeysvalueof{/pgf/pattern keys/radius}];
} }
\begin{tikzpicture}
\draw[pattern={hexa with circles[size=10pt,line width=.8pt,angle=90]},
pattern color=blue] (0,0) rectangle ++(2,2); 
\draw[pattern={hexa with circles[size=10pt,line width=.8pt,angle=0]},
pattern color=red] (3,0) rectangle ++(2,2); 
\end{tikzpicture}
\end{document}

enter image description here

ADDENDUM: To make @BlackMild a bit happier here is a shorter version. Of course, one could make it much shorter by using hardcoded values for the distances and so on, but this IMHO really defeats the purpose.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{patterns.meta} 
\begin{document}
\def\pk#1{\pgfkeysvalueof{/pgf/pattern keys/#1}}
\tikzdeclarepattern{name=hexa with circles,
  parameters={
      \pk{size},
      \pk{angle},
      \pk{line width},
      \pk{radius},
  },
  bounding box={(-.1pt,-.1pt) and
    (1.5*\pk{size}+.1pt,
     {sin(60)*\pk{size}+.1pt})},
  tile size={(1.5*\pk{size},
              {sin(60)*\pk{size}})},
  tile transformation={rotate=\pk{angle}},
  defaults={
    size/.initial=5pt,
    angle/.initial=0,
    line width/.initial=.4pt,
    radius/.initial=1.2pt,
}, code={
\draw[line width=\pk{line width}] 
(0,{\pk{size}*sin(60)/2}) -- ({\pk{size}*1/4},0) -- ({\pk{size}*3/4},0) -- (\pk{size},{\pk{size}*sin(60)/2})
(0.75*\pk{size},{\pk{size}*sin(60)})-- (\pk{size},{\pk{size}*sin(60)/2}) -- (1.5*\pk{size},{\pk{size}*sin(60)/2})-- (1.75*\pk{size},{\pk{size}*sin(60)});
\fill (0,{\pk{size}*sin(60)/2}) circle[radius=\pk{radius}] ({\pk{size}*1/4},0) circle[radius=\pk{radius}]
({\pk{size}*3/4},0) circle[radius=\pk{radius}] (\pk{size},{\pk{size}*sin(60)/2}) circle[radius=\pk{radius}];
} }
\begin{tikzpicture}
\draw[pattern={hexa with circles[size=10pt,line width=.8pt,angle=90]},
pattern color=blue] (0,0) rectangle ++(2,2); 
\draw[pattern={hexa with circles[size=10pt,line width=.8pt,angle=0]},
pattern color=red] (3,0) rectangle ++(2,2); 
\end{tikzpicture}
\end{document}

ADDENDUM 2: An attempt to address your (updated) question. Apart from rotating the patterns, you can also subject them to other transformations, in particular shifts.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{patterns.meta} 
\begin{document}
\def\pk#1{\pgfkeysvalueof{/pgf/pattern keys/#1}}
\tikzdeclarepattern{name=hexa with circles,
  parameters={
      \pk{size},
      \pk{angle},
      \pk{line width},
      \pk{radius},
      \pk{xshift},
      \pk{yshift},
  },
  bounding box={(-.1pt,-.1pt) and
    (1.5*\pk{size}+.1pt,
     {sin(60)*\pk{size}+.1pt})},
  tile size={(1.5*\pk{size},
              {sin(60)*\pk{size}})},
  tile transformation={xshift=\pk{xshift},yshift=\pk{yshift},rotate=\pk{angle}},
  defaults={
    size/.initial=5pt,
    angle/.initial=0,
    line width/.initial=.4pt,
    radius/.initial=1.2pt,
    xshift/.initial=0pt,
    yshift/.initial=0pt,
}, code={
\draw[line width=\pk{line width}] 
(0,{\pk{size}*sin(60)/2}) -- ({\pk{size}*1/4},0) -- ({\pk{size}*3/4},0) -- (\pk{size},{\pk{size}*sin(60)/2})
(0.75*\pk{size},{\pk{size}*sin(60)})-- (\pk{size},{\pk{size}*sin(60)/2}) -- (1.5*\pk{size},{\pk{size}*sin(60)/2})-- (1.75*\pk{size},{\pk{size}*sin(60)});
\fill (0,{\pk{size}*sin(60)/2}) circle[radius=\pk{radius}] ({\pk{size}*1/4},0) circle[radius=\pk{radius}]
({\pk{size}*3/4},0) circle[radius=\pk{radius}] (\pk{size},{\pk{size}*sin(60)/2}) circle[radius=\pk{radius}];
} }
\begin{tikzpicture}
\draw[pattern={hexa with circles[size=2cm,line width=.8pt,radius=1.4pt,
xshift={-0.42*sin(60)*0.5cm},
yshift={-1.33*cos(60)*0.5cm}]},
pattern color=red] (-8,-8) rectangle ++(16,16); 
 \draw [color=red,mark=*] plot[samples at={-180,-120,...,180},variable=\x] 
  (\x:1);
  \node[color=black, left] at (-1,0) {\small (-1,0)};
  \node[color=black, left] at  (-0.5,0.866) {\small (-0.5,0.866)};
  \node[color=black, left] at  (-0.5,-0.866) {\small (-0.5,-0.866)};
  \node[color=black, right] at (1,0) {\small (1,0)};
  \node[color=black, right] at  (0.5,0.866) {\small (0.5,0.866)};
  \node[color=black, right] at  (0.5,-0.866) {\small (0.5,-0.866)};
\end{tikzpicture}
\end{document}

enter image description here

  • Can you make your code as simple as possible? or I will do it when i am free – Black Mild Oct 26 '19 at 16:44
  • 2
    @BlackMild It is already "simple" given that it is flexible, i.e. does not use hard coded distances and so on as the other answer. If you mean whether or not one could make it shorter: yes, this is possible at the expense of introducing a macro and slightly decreasing the performance. – Schrödinger's cat Oct 26 '19 at 16:47
  • 1
    @SC: Thanks! I am a bit happier now ^^ – Black Mild Oct 27 '19 at 19:14
6

If you need only the hexagons, use for example (xelatex or latex->dvips->ps2pdf). Can be simplified by another \multido loop

\documentclass{article}
\usepackage{pst-poly,multido}
\begin{document}

\begin{pspicture}[showgrid](-1.1,0.1)(5,-2)
\multido{\rA=-0.5+1.5}{4}{\rput(\rA,-0.5){\PstHexagon[unit=0.5]}}
\multido{\rA=0.25+1.5}{4}{\rput(\rA,-0.933){\PstHexagon[unit=0.5]}}
\multido{\rA=-0.5+1.5}{4}{\rput(\rA,-1.366){\PstHexagon[unit=0.5]}}
\multido{\rA=0.25+1.5}{4}{\rput(\rA,-1.799){\PstHexagon[unit=0.5]}}
\end{pspicture}

\bigskip
\begin{pspicture}(-1.1,0.1)(5,-2)
\psset{linecolor=red,linewidth=1.5pt}
\providecommand{\PstPolygonNode}{\psdots[dotscale=1.2](1;\INode)}
\multido{\rA=-0.5+1.5}{4}{\rput(\rA,-0.5){\PstHexagon[unit=0.5]}}
\multido{\rA=0.25+1.5}{4}{\rput(\rA,-0.933){\PstHexagon[unit=0.5]}}
\multido{\rA=-0.5+1.5}{4}{\rput(\rA,-1.366){\PstHexagon[unit=0.5]}}
\multido{\rA=0.25+1.5}{4}{\rput(\rA,-1.799){\PstHexagon[unit=0.5]}}
\end{pspicture}

\bigskip
\begin{pspicture}(-1.1,0.1)(5,-2)
\psset{linecolor=blue,linewidth=1.5pt,PolyRotation=30}
\providecommand{\PstPolygonNode}{\psdots[dotscale=1.2](1;\INode)}
\multido{\rA=-0.5+0.866}{6}{\rput(\rA,-0.5){\PstHexagon[unit=0.5]}}
\multido{\rA=-0.067+0.866}{6}{\rput(\rA,-1.25){\PstHexagon[unit=0.5]}}
\multido{\rA=-0.5+0.866}{6}{\rput(\rA,-2){\PstHexagon[unit=0.5]}}
\multido{\rA=-0.067+0.866}{6}{\rput(\rA,-2.75){\PstHexagon[unit=0.5]}}
\end{pspicture}
\end{document}

enter image description here

If you need it as a background filling, use it as (run with latex->dvips->ps2pdf)

\documentclass{article}
\usepackage[tiling]{pst-fill}
\newcommand\Tiling[2][]{% 
 \begin{pspicture}#2
   \psframe[fillstyle=boxfill,#1]#2
 \end{pspicture}}
\newcommand\Hexagon[1][showpoints,dotscale=2]{% sin(60)=0.866
  \begin{pspicture}(0.866,0.75)
    \pspolygon[dimen=middle,#1](0.5;30)(0.5;90)(0.5;150)(0.5;210)(0.5;270)(0.5;330) 
  \end{pspicture}}

\begin{document}
\psboxfill{\Hexagon} 
\Tiling[fillcyclex=2,fillloopaddy=1]{(5,5)}
\psboxfill{\Hexagon[]} 
\Tiling[fillcyclex=2,fillloopaddy=1]{(5,5)}

\psboxfill{\Hexagon} 
\Tiling[fillcyclex=2,fillloopaddy=1,fillangle=30]{(5,5)}
\psboxfill{\Hexagon[]} 
\Tiling[fillcyclex=2,fillloopaddy=1,fillangle=30]{(5,5)}
\end{document}

enter image description here

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.