[Tex/LaTex] TiKZ matrix of objects

matricesnodesscalingtikz-pgf

I am drawing diagrams which consist of grids, some cells of which are filled with circles, like this:

enter image description here

I created this picture with

\begin{tikzpicture}[scale=0.6]
  \draw[shift={(0.5,0.5)}] (0,0) grid (6,6);
  \foreach \x in {0,1,...,5} {
    \node at (\x+1,7) {$\x$};
    \node[left] at (0,6-\x) {$\x$};
  }
  \foreach \x in {2,3,4,5} {
     \foreach \y in {3,4} {
        \fill (\x,\y) circle(0.2);
        \fill (\y,\x) circle(0.2);
     }
  }
\end{tikzpicture}

Now in this picture the dots are nicely symmetric, so I can place them with some neat \foreach statements. But in other diagrams the dots are more randomly scattered, and so I need some way of entering them one by one.

This works (for a different diagram):

\begin{tikzpicture}[circ/.style = {circle,radius=2mm,fill=black},scale=0.6]
\draw[shift={(0.5,0.5)}] (0,0) grid (6,6);
  \foreach \x in {0,1,...,5} {
    \node at (\x+1,7) {$\x$};
    \node[left] at (0,6-\x) {$\x$};
  }
\matrix[matrix of nodes,row sep=2.8mm,column sep=2.8mm,shift={(2.1,2.1)}] {
\node[circ] {}; & \node[circ] {}; & \node[circ] {}; &&&\\
\node[circ] {}; & \node[circ] {}; & \node[circ] {}; &&&\\
\node[circ] {}; & \node[circ] {}; & \node[circ] {}; & \node[circ] {};&&\\
&&\node[circ] {}; & \node[circ] {}; & \node[circ] {};\\
&&&\node[circ] {}; & \node[circ] {}; & \node[circ] {};\\
&&&\node[circ] {}; & \node[circ] {}; & \node[circ] {};\\
};
\end{tikzpicture}

But it's a pain getting the matrix lined up in the right place. Also, I don't seem to be able to scale the circles properly – they end up filling the entire cell like this:

enter image description here

which is clearly not what I want.

So – how do I use matrix in TiKZ to fill certain cells in a grid with small circles? Or is there another, better, way?

Best Answer

I would draw the grid using \matrix instead, as doing so provides anchors like m-i-j (as the ith row and jth column of the matrix) which you can later access in drawing circles.

I've automated stuff a bit by defining a \mygrid command, which takes two arguments that specify the dimension of the grid. (If it's always a square, then the command can be simplified by dropping the second argument.)

In terms of scaling, the circles themselves can be scaled by passing the scale option to tikzpicture, and if you want to scale the grid, pass the scale option to \mygrid.

MWE

\documentclass{article}

\usepackage{tikz,etoolbox}
\usetikzlibrary{matrix}

\newcommand\mygrid[3][]{      % this definition uses \foreach inside a matrix
  \let\mymatrixcontent\empty  % see http://tex.stackexchange.com/q/60394/18228
  \newcommand{\row}{%
    \foreach \j in {1,...,#2}{
      \foreach \i in {1,...,#3} {%
        \begingroup\edef\x{\endgroup
           \noexpand\gappto\noexpand\mymatrixcontent{|[draw,minimum size=1cm,#1]| \&}}\x
        }%
      \gappto\mymatrixcontent{\\}%
    }
  }
  \row
  \matrix(m)[matrix of nodes,ampersand replacement=\&,row sep=-\pgflinewidth,column sep=-\pgflinewidth]{
    \mymatrixcontent
  };
  \foreach \x[count=\i from 0] in {1,...,#2}\node[left] at (m-\x-1.west) {$\i$};
  \foreach \y[count=\j from 0] in {1,...,#3}\node[above] at (m-1-\y.north) {$\j$};
}

\begin{document}

\begin{tikzpicture}[scale=.5,]
\mygrid[scale=.6]{6}{8} % two extra columns just for demonstration

\foreach\j[count=\i,remember=\i as \x(initially 3)] in{1,...,6}{
  \filldraw(m-\i-\j)circle[radius=2pt];
  \filldraw(m-\x-\j)circle[radius=2pt];
  \filldraw(m-\j-\x)circle[radius=2pt];
  \filldraw(m-6-4)circle[radius=2pt];
}
\end{tikzpicture}
\end{document}

Output

enter image description here