3

I'm trying to draw a grid of nodes of specific size. In addition, I'm poking holes into this grid by trying to make the cells and in particular their inner borders white. To make this concrete, consider the following:

\documentclass[tikz]{standalone}
\usetikzlibrary{fit, matrix}

\begin{document}

\begin{tikzpicture} \matrix [ matrix of nodes, inner sep=0pt, % no padding around the cells row sep=-\pgflinewidth, column sep=-\pgflinewidth, nodes={ rectangle, draw=black, minimum height=11mm, minimum width=11mm, anchor=center, inner sep=0pt, outer sep=0pt }, nodes in empty cells, name=table ] { & & & & \ & & |[white]| & & \ & |[white]| & |[white]| & & \ & & |[white]| & |[white]| & \ & & & & \ };

\end{tikzpicture} \end{document}

In general, suppose we have arbitrary "islands" of white cells in the matrix; in this case, we just have one island (of size 5), meaning the white cells span a connected subgraph of the host grid, but there could be several such islands.

We want the inner borders not be drawn, but the outer borders should be left untouched. As it is, the outer borders get drawn with just their edges showing, making them look gray-ish. See below for the non-wanted output:

enter image description here

How can we better control how the nodes and their edges get drawn? I also see this question which might help me draw these in a nicer way: I'm doing this programmatically so it seems nice to be able to specify the island coordinates in a list-like manner.

mrm
  • 189

3 Answers3

5

Instead of drawing a white border, just don't draw any border. That way you won't get gray lines (which are actually white on top of black).

In the code below, matrix of grid nodes = <rows> x <columns> sets up a TikZ matrix with the specified numbers of rows and columns where each cell just has \node{}; in it. By default, each of these node will be a grid node.

By using the island(s) keys, the cells where a grid island node should be used instead can be specified. A grid island node is simply path only (i.e. draw = none, fill = node, …) but could be anything, maybe just a coordinate (but that would need you to do a row sep or column sep with between origins otherwise you get a zero-sized row or column if a whole row or column contains islands.

Instead of \node{}; we could place \tikzgridnode in each cell which does \node[grid node]{}; usually but can just put nothing at all in a cell if it's an island (not even a coordinate).

Code

\documentclass[tikz]{standalone}
\makeatletter
\newcommand*\utilrepeat[2]{%
  \ifnum#1=1 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {#2}{#2\expandafter\utilrepeat\expandafter{\the\numexpr#1-1\relax}{#2}}}
\makeatother
\tikzset{
  grid node/.style={
    shape=rectangle, draw=black, fill=lightgray, anchor=center,
    minimum size=+11mm, inner sep=+0pt, outer sep=+0pt},
%  grid island node/.style={shape=coordinate}, % no node, just a coordinate
  grid island node/.style=path only,         % node but no output
  tight matrices/.style={every outer matrix/.append style={inner sep=+0pt}},
  matrix of grid nodes/.style args={#1x#2}{
    matrix, tight matrices, nodes=grid node,
    row sep=+-\pgflinewidth, column sep=+-\pgflinewidth,
    execute at empty cell=\node{};,
    node contents=%
      \utilrepeat{#1}{%
        \utilrepeat{\pgfinteval{#2-1}}{\pgfmatrixnextcell}\pgfmatrixendrow}},
  island/.style args={#1-#2}{
    row #1 column #2/.append style={nodes=grid island node}},
  islands/.style={island/.list={#1}}}
\begin{document}
\tikz\node[matrix of grid nodes = 5 x 5, islands = {2-3, 3-2, 3-3, 4-3, 4-4}];
\end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
3

A simple, maybe a bit rude solution by defining cells style without borders:

\documentclass[border=6pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document} \begin{tikzpicture} \newcommand\nx{|[draw=none]|} \matrix (m) [matrix of nodes, row sep=-\pgflinewidth, column sep=-\pgflinewidth, nodes = {draw, minimum size=11mm, anchor=center, inner sep=0pt, outer sep=0pt} ] { a & b & c & d & e\ f & g & \nx h & i & j\ k & \nx l & \nx m & n & o\ p & q & \nx r & \nx s & t\ u & v & w & x & y\ }; \end{tikzpicture} \end{document}

enter image description here

Zarko
  • 296,517
2

The command \islands below takes 3 arguments. The first argument is the number of rows, the second argument is the number of columns and the third argument is a list of cells in the form (<row>,<column>).

This command draws horizontal and vertical lines. A horizontal line is not drawn if the cell above and below is contained in the list in the third argument. Similarly for vertical lines.

enter image description here

\documentclass[border=6pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\ExplSyntaxOn
\cs_generate_variant:Nn \str_if_in:nnT { neT }
\bool_new:N \l__islands_bool
\NewDocumentCommand { \islands } { mmm }
% #1 number of rows
% #2 number of columns
% #3 list of cells in the form (<row>,<column>)
  {
    \begin { scope }
      [
        shift = { ( mymatrix-1-1.north~west ) } ,
        x = 11 mm ,
        y = -11 mm
      ]
      \int_step_inline:nnn { 0 } {#1}
        {
          \int_step_inline:nn {#2}
            {
              \bool_set_true:N \l__islands_bool
              \str_if_in:neT {#3} { ( ##1 , ####1 ) }
                {
                  \str_if_in:neT {#3} { ( \int_eval:n { ##1 + 1 } , ####1 ) }
                    {
                      \bool_set_false:N \l__islands_bool
                    }
                }
              \bool_if:NT \l__islands_bool
                { \draw ( { ####1 - 1 } , ##1 ) --++ ( 1 , 0 ) ; }
            }
        }
      \int_step_inline:nnn { 0 } {#2}
        {
          \int_step_inline:nn {#1}
            {
              \bool_set_true:N \l__islands_bool
              \str_if_in:neT {#3} { ( ####1 , ##1 ) }
                {
                  \str_if_in:neT {#3} { ( ####1 , \int_eval:n { ##1 + 1 } ) }
                    {
                      \bool_set_false:N \l__islands_bool
                    }
                }
              \bool_if:NT \l__islands_bool
                { \draw ( ##1 , { ####1 - 1 } ) --++ ( 0 , 1 ) ; }
            }
        }
    \end { scope }
  }
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\matrix (mymatrix) [
  matrix of nodes,
  inner sep=0pt,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={
    rectangle,
    minimum height=11mm,
    minimum width=11mm,
    anchor=center,
    inner sep=0pt,
    outer sep=0pt
  }
]
  {
    a & b & c & d & e\\
    f & g & h & i & j\\
    k & l & m & n & o\\
    p & q & r & s & t\\
    u & v & w & x & y\\
  };
\islands{5}{5}{(2,3),(3,2),(3,3),(4,3),(4,4)}
\end{tikzpicture}
\end{document}
matexmatics
  • 4,819