3

Now that I have seen how to use PGF/TikZ to create a square 3x3 grid of points and draw a polygon between these points, I'd like to create a grid of such grids, like this:

Grid of grids

How can I produce it using PDF/TikZ? I'd like each polygon to be specified in a relative coordinate system, so that I can easily change the order of the polygons.

3
  • The relative system you're talking about can be obtained by using the --++ option for the \draw command. What have you tried so far? We need more informations to help you.
    – SebGlav
    Commented Nov 3, 2022 at 9:34
  • @SebGlav: I've tried nothing. I don't know how to approach the problem. I'm not familiar with PGF/TikZ (rather, I used to be a little familiar with it, but it was long ago and I have forgotten everything).
    – Evan Aad
    Commented Nov 3, 2022 at 9:36
  • See my answer to How to draw a grid of grids-of-polygons without explicitly specifying the positions of the grids-of-polygons? where the polygons are defined with pics and organized into a matrix.
    – Ignasi
    Commented Nov 3, 2022 at 20:14

4 Answers 4

6

In this case you can create a macro for the grid and then use scopes to change the coordinate system. Or, if the distance between grids is the same as the distance between points, you can do one bigger grid ant then the scopes.

For example, with multiple grids:

\documentclass[tikz,border=2mm]{standalone}

% grid
\newcommand{\mygrid}
{
  \foreach\i in {0,...,2} \foreach\j in {0,...,2}
    \fill (\i,\j) circle (1pt);
}

\begin{document}
\begin{tikzpicture}
[% options
   line join=round,
   %scale=1.5
]
% first polygon
\begin{scope}
  \draw[thick,blue] (0,0) -- (2,2) |- cycle;
  \mygrid
\end{scope}
% second polygon
\begin{scope}[shift={(3,0)}]  % <-- this changes the coordinate system
  \draw[thick,blue] (0,0) -- (1,1) -- (1,2) -- (2,1) |- cycle;
  \mygrid
\end{scope}
% third polygon
\begin{scope}[shift={(6,0)}]  % <-- this changes the coordinate system
  \draw[thick,blue] (0,0) -- (1,1) -- (0,2) -- (2,1) |- cycle;
  \mygrid
\end{scope}
% fourth polygon
\begin{scope}[shift={(0,-3)}] % <-- this changes the coordinate system
  \draw[thick,blue] (0,0) -- (1,1) -- (0,2) -- (1,2) -- (2,0) -- cycle;
  \mygrid
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

8

I love an overengineered solution.

This consists of

  • A custom TikZ coordinate system (dot grid cs: <num>) that takes its argument and converts it into

    ( mod(<num>-1,<grid width>), int((<num>-1)/<grid height>) )
    

    This means, for a 3×3 grid the number 1, …, 9 correspond to the nine dots that are arranged like the numbers on a calculator

    7 8 9
    4 5 6
    1 2 3
    

    or a phone

    1 2 3
    4 5 6
    7 8 9
    

    if the y axis is inverted.

    For sizes greater than 3×3 these numbers get a little bit uncomfortable but we could adjust the dot grid cs so that it interprets <x>/<y> as (<x>, <y>) usual so that we could also specify the points on the polygon by their x and y value. (The / is preferred over the , since the , would need to be protected from the .list parser.)

  • A grid (dots) that is setup in a way that the dots are actual line segments of length zero but turned into dots via line cap=round (this might be viewer-dependent). The style grid determines the output of the grid (the line width will be the diameter of the dots). The x vec dash style makes sure that the cheaty dash pattern uses the current x vector.

    This can changed by either

    • changing the grid style (for a different color) or
    • changing the diameter value that is used by the default as the line width.

    If this makes trouble, you can replace the dots style with the one that's commented that uses circular nodes.

  • The key do that actually draws the polygon by using the dot grid coordinate system. After the polygon is drawn and closes, dots is called that puts the grid on top of the polygon like in the other answers.

I've put all keys in the polygon dot grid name space so that it can't conflict with any original TikZ keys. The polygon dot grid key is setup so that it can be used use multiple keys in the namespace without having to prefix it everytime.


A few more keys, namely dos, dos*, Dos and Dos* allow multiple polygons with the syntax {{poly 1}, {poly 2}, …, {poly n}}.

The starred version draws closed polygons. The capital D indicates the version that also draws the dots but those are always available with the key dots anyway. If you want to use open and closes polygons in the same grid you need to use dos and dos* where the last instance can be a capital version (so that the dots are only drawn once).


I've also added grid poly as a shortcut to do* and a few grid poly sizes.

And then it's just a matter of

\tikz\draw[polygon dot grid={do*={2,4,8,6}, dots}];
\tikz[grid poly size=normal]\draw[red,            grid poly={2,4,8,6}];
\tikz[grid poly size=small] \draw[blue,           grid poly={2,4,8,6}];
\tikz[grid poly size=tiny]  \draw[green!50!black, grid poly={2,4,8,6}];
\tikz \draw[polygon dot grid={do*={4,5,7}, Dos={{1,2},{8,9}}}];
\tikz \draw[green, polygon dot grid/dos*={{1,2,4}, {5,6,8}}]
    {[
      scale=.5,
      polygon dot grid={size=5x5, do={21,12,8,5}}
    ]} [polygon dot grid/dots=red];

which would draw

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


As always with TikZ/PGFkeys you can set these settings globally or use another macro or style to do some of these things (which I'm using in the \matrix with \tikzGridPoly).


Since you want to draw more than one of these grid, we can use a \matrix which allows us to put a separate drawing in a tabular-like alignment.

Since I don't like to repeat myself I setup the cells (→ polygon dot grid/matrix) so that they're using \tikzGridPoly by default. This means, the content of a cell needs to be a list of points (plural!) on the polygon enclosed in {} – or {\onlyGrid} as a special case to only draw the grid.

With execute at empty cell=\tikzGridPoly{\onlyGrid} we also could make an empty cell have a grid but maybe you actually want insert empty spaces between the grids as well.

Code

\documentclass[tikz]{standalone}

\tikzset{
  polygon dot grid/.code=\pgfqkeys{/tikz/polygon dot grid}{#1},
  polygon dot grid={
    x dots/.initial=3, y dots/.initial=3, diameter/.initial=+3pt,
    polygon/.style = blue, % default style for \tikzGridPoly
    dots/.default=,
    grid/.style={
      black, line width=\pgfkeysvalueof{/tikz/polygon dot grid/diameter}}},
  polygon dot grid/dimension/.style args={#1x#2}{/tikz/x={#1}, /tikz/y={#2}},
  polygon dot grid/size/.style args={#1x#2}{
      /tikz/polygon dot grid/x dots={#1}, /tikz/polygon dot grid/y dots={#2}},
  polygon dot grid/dots/.style={
    /tikz/insert path={(0,0) edge[x vec dash,
      to path={grid (\tikztotarget)}, polygon dot grid/grid, #1]
        (\pgfkeysvalueof{/tikz/polygon dot grid/x dots}-1,%
         \pgfkeysvalueof{/tikz/polygon dot grid/y dots}-1)}},
%  polygon dot grid/dots/.style={/tikz/insert path={foreach[parse=true]\i in {
%       1,...,\pgfkeysvalueof{/tikz/polygon dot grid/x dots}
%            *\pgfkeysvalueof{/tikz/polygon dot grid/y dots}} {
%    node[at=(dot grid cs:\i), polygon dot grid/grid, shape=circle,
%      inner sep=+0pt, draw=none, fill, node contents=,
%      minimum size=\pgfkeysvalueof{/tikz/polygon dot grid/diameter}, #1]}}},
  polygon dot grid/do/.style args={#1,#2}{
    /tikz/insert path={(dot grid cs:#1)},      % start polygon
    /tikz/polygon dot grid/lineto/.list={#2}}, % lines to other points,
  polygon dot grid/do*/.style={
    /tikz/polygon dot grid/do={#1}, % normal polygon
    /tikz/insert path={--cycle}},   % but closed
  %% dos  = multiple        polygons
  %% dos* = multiple closed polygons
  %% Dos  = multiple        polygons with dots on top
  %% Dos* = multiple closed polygons with dots on top
  polygon dot grid/dos/.style ={/tikz/polygon dot grid/do/.list={#1}},
  polygon dot grid/dos*/.style={/tikz/polygon dot grid/do*/.list={#1}},
  polygon dot grid/Dos/.style ={/tikz/polygon dot grid={dos={#1},  dots}},
  polygon dot grid/Dos*/.style={/tikz/polygon dot grid={dos*={#1}, dots}},
  polygon dot grid/lineto/.style={/tikz/insert path={--(dot grid cs:#1)}},
  polygon dot grid/matrix/.style={
    /tikz/execute at begin cell=\tikzGridPoly,
    /utils/exec=\def\onlyGrid{\onlyGrid}%
     \def\tikzGridPoly##1{%
        \ifx\onlyGrid##1\path[polygon dot grid/dots];
        \else\draw[polygon dot grid/polygon, polygon dot grid={do*={##1},dots}];\fi}},
}
\tikzdeclarecoordinatesystem{dot grid}{%
  \pgfpointxy{mod(#1-1,\pgfkeysvalueof{/tikz/polygon dot grid/x dots})}
             {int((#1-1)/(\pgfkeysvalueof{/tikz/polygon dot grid/y dots}))}}
\makeatletter
\tikzset{x vec dash/.style={dash pattern={on 0pt off veclen(\pgf@xx,\pgf@xy)},
                                             line cap=round, ystep=0, xstep=1}}
\makeatother

\tikzset{
  grid poly/.style={polygon dot grid/do*={#1}, polygon dot grid/dots},
  grid poly size/.is choice,
  grid poly size/normal/.style={
    very thick, polygon dot grid={dimension=1cmx1cm, diameter=+3pt}},
  grid poly size/small/.style={
    thin,       polygon dot grid={dimension=7.5mmx7.5mm, diameter=+2pt}},
  grid poly size/tiny/.style={
    thin,       polygon dot grid={dimension=5mmx5mm, diameter=+1.3333pt}},
}
\begin{document}
\tikz\matrix[row sep=5mm, column sep=5mm,
    polygon dot grid={matrix, diameter=1.333pt, dimension=4mm x 4mm}]{
  {1,3,9}       & {1,3,6,8,5}   & {1,3,6,7,5}   & {1,3,6,5,8} & {1,3,6,4}     \\
  {1,3,8,7,5}   & {1,3,8,4,5}   & {1,3,8}                                     \\
  {1,6,9,8,4,5} & {1,6,9,8}     & {1,6,9,8,5,4} & {1,6,9,4}   & {1,6,9,5,8,4} \\
  {1,6,8,7,4,5} & {1,6,8,7,5,4} & {1,6,8,4}     &             & {\onlyGrid}   \\
};

\tikz\draw[polygon dot grid={do*={2,4,8,6}, dots}];
\tikz[grid poly size=normal]\draw[red,            grid poly={2,4,8,6}];
\tikz[grid poly size=small] \draw[blue,           grid poly={2,4,8,6}];
\tikz[grid poly size=tiny]  \draw[green!50!black, grid poly={2,4,8,6}];
\tikz \draw[polygon dot grid={do*={4,5,7}, Dos={{1,2},{8,9}}}];
\tikz \draw[green, polygon dot grid/dos*={{1,2,4}, {5,6,8}}]
    {[ % This is nasty.
      scale=.5,
      polygon dot grid={size=5x5, do={21,12,8,5}}
    ]} [polygon dot grid/dots=red];
\end{document}

Output

enter image description here

10
  • Thank you, this is beautiful! How do I need to change your code, if I want the points of the dotted grids to be numbered from the bottom up, like the pattern on a calculator?
    – Evan Aad
    Commented Nov 3, 2022 at 11:39
  • 2
    @EvanAad Replace y=-4mm by y=4mm (or any positive distance) in the options of the \matrix (as I did in the updated answer). I've also moved the defintion of ``\tikzGridPoly` inside of grid pf polygon grids so that it isn't defined globally where we don't need it. Commented Nov 3, 2022 at 12:33
  • 1
    @EvanAad I've changed my answer again to put all keys in their own name space. I hope the examples are clear enough. Besides, you can always use other (shorter) styles do to something, for example dia/.style={polygon dot grid/diameter={#1}}. This way, even grid poly is just a shortcut to polygon dot grid/do. And you can always set the diameter in your preamble and it would be used in your whole document unless you change it. Commented Nov 3, 2022 at 14:06
  • 1
    @EvanAad Because the polygon dot grid/polygon style is only used with \tikzGridPoly that is only defined inside the \matrix – admittedly not a good setup. ☹ You can remove it there and put it inside the polygon dot grid/do style for a more consistent solution. (But that will overwrite any color specification before the do.) It really depends on your diagrams and how flexible you want to be when it comes to specifying the options of the polygon line. Commented Nov 3, 2022 at 14:42
  • 1
    @EvanAad I've updated my answer yet again. I've opted for the syntax like {{1,2}, {8,9}} because that's just a loop of polygons (which are also basically a loop). I've changed the original do to not draw a closed polygon anymore. The closed polygons are drawn by the starred versions. Multiply polygons are then specified via the dos/dos* keys where the capital versions also draw the dots (but you can always specify dots manually which I changed so that it accepts now arbitrary options that are forwarded to the internal grid). Commented Nov 3, 2022 at 16:55
3

Taking your last qquestion as a reference, here's a way to draw the same polygon but using relative coordinates. Only the first coordinate is absolute (here (0,0)):

graph grid polygon

\documentclass[tikz,border=3.14mm]{standalone}

\begin{document}
    \begin{tikzpicture}
        \draw[thick,blue] (0,0) --++ (1,0) --++ (1,1) --++ (0,1) --++ (-1,0) --++ (0,-1) --++ (-1,-1) -- cycle;
        % grid
        \foreach\i in {0,...,2} \foreach\j in {0,...,2}
            \fill (\i,\j) circle (1pt);
    \end{tikzpicture}
\end{document}
2
  • Thank you, but this is only a partial answer. I'd like to create a grid of grids-of-polygons, and not just one as in your current answer.
    – Evan Aad
    Commented Nov 3, 2022 at 9:47
  • That was meant to let you start. Sometimes, it's better to try by oneself. That's how I learnt TikZ.
    – SebGlav
    Commented Nov 3, 2022 at 12:14
3

I propose to draw each particular polygon inside a pic. This way it's easy to build a matrix of pics just using their names.

A correct distance for column sep and row sep helps to get a continous grid.

With the help of tikz.transformations.mirror library (from tikz-ext package) it's easy to transform the polygons with having to define new ones.

\documentclass[border=2mm,tikz]{standalone}

\usetikzlibrary{ext.transformations.mirror}

\newcommand{\grid}{\foreach \i in {0,1,2} \foreach \j in {0,1,2}
            \fill (\i,\j) circle (1pt);}
            
\tikzset{
    line join=round,
    polygon/.style={thick, blue},
    empty/.pic={
        \grid
    },
   one/.pic={
        \grid
        \draw[polygon] (0,0)--(2,2)|-cycle;
    },
   two/.pic={
        \grid
        \draw[polygon] (0,0)-|(2,1)--(1,2)--(1,1)--cycle;
    },
   three/.pic={
        \grid
        \draw[polygon] (0,0)-|(2,1)--(0,2)--(1,1)--cycle;
    },
   four/.pic={
        \grid
        \draw[polygon] (0,0)-|(2,1)-|(1,2)--cycle;
    },
   five/.pic={
        \grid
        \draw[polygon] (0,0) rectangle ++(2,1);
    },
   six/.pic={
        \grid
        \draw[polygon] (0,0)--(2,0)--(1,2)--(0,2)--(1,1)--cycle;
    },
   seven/.pic={
        \grid
        \draw[polygon] (0,0)--(2,0)--(1,2)--(0,1)--(1,1)--cycle;
    },
   eight/.pic={
        \grid
        \draw[polygon] (0,0)--(2,0)--(1,2)--cycle;
    },
   nine/.pic={
        \grid
        \draw[polygon] (0,0)--(1,0)--(2,1)|-(1,2)--(1,1)--cycle;
    },
   ten/.pic={
        \grid
        \draw[polygon] (0,0)--(1,0)--(2,1)--(2,2)--(1,1)--(1,2)--cycle;
    },
}

\begin{document}

\begin{tikzpicture}
  \matrix [column sep={3cm,between origins}, row sep={3cm,between origins}] {
      \pic{one}; & \pic{two}; & \pic{three}; & \pic{four}; & \pic{empty};\\
      \pic{five}; & \pic{six}; & \pic{seven}; & \pic{eight}; & \pic{nine}; \\
      \pic{ten}; & \pic[xmirror={(1,1)}]{ten}; & 
      \pic[ymirror={(1,1)}]{ten}; &
      \pic[xmirror={(1,1)}, ymirror={(1,1)}]{ten}; &
      \pic[mirror={(0,2)--(2,0)}]{ten}; \\
    };
\end{tikzpicture}

\end{document}

enter image description here

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .