2

I'm trying to build a tikz matrix where each cell will either be empty, contain an image or a part of an image. That is, a single image if it's large may span multiple cells.

I'm using the following test image called kings from OpenClipart with the following code:

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

\begin{document}
\begin{tikzpicture}
\matrix [
    matrix of nodes,
    row sep=-\pgflinewidth,
    column sep=-\pgflinewidth,
    nodes={
        rectangle, draw=black, minimum height=11mm, minimum width=11mm,
        anchor=center, inner sep=0pt, outer sep=0pt, font=\Huge
    },
    nodes in empty cells,
    name=table
] {    
 &  &  &  &  \\
 &  &  &  &  \\
 &  &  &  &  \\
 &  &  &  &  \\
};

% Using draw just to make the problem clear
\node[fit=(table-2-3)(table-2-4), draw]{
% This works, but is there a more robust way?
%\vspace{-0.1cm}
\includegraphics[width=22mm, height=11mm]{kings}
};

\node[fit=(table-3-1)(table-4-2), draw]{
%\vspace{-0.1cm}
\includegraphics[width=22mm, height=11mm]{kings}
};

\end{tikzpicture}
\end{document}

This produces the following output:

enter image description here

Here, I'm using draw just to make the issue clear: it seems that the lower part of the image is used for centering, so to say. By using negative vspace I can make this look OK, but it doesn't seem that nice or robust. Is there a better way?

As an additional problem, I would want the grid lines inside of the image to disappear (i.e., the image should be drawn over the inner lines of the grid), but the outer lines should remain intact. Similarly, I can "almost" do this by doing something like draw=white, but it results in an effect like (the black line above the image breaks because a white rectangle is drawn around the image):

enter image description here

The answer here helped me closer to the goal, but is only considering a single image within a single node.

1
  • If you're actually building chess diagrams there might be better solutions out there, for example the package chessboard. Jul 17, 2022 at 1:03

1 Answer 1

1

The manual states for the fit library:

The exact effects of the fit option are the following:

  1. […]
  2. […]
  3. […]
  4. […]
  5. […]
  6. After the node has been typeset, its height and depth are adjusted such that they add up to the height of the computed bounding box and such that the text of the node is vertically centered inside the box.

The above means that, generally speaking, if the node contains text like box in the above example, it will be centered inside the box. It will be difficult to put the text elsewhere, in particular, changing the anchor of the node will not have the desired effect. Instead, what you should do is to create a node with the fit option that does not contain any text, give it a name, and then use normal nodes to add text at the desired positions. Alternatively, consider using the label or pin options.

This means that the created node will have a text height=5.5mm and a text depth=5.5mm. Your picture has only a height, not a depth and that pushes it up.

The easiest solution is to follow the manual's advice.

We will use a fitted node with no text and use the label key to place another node at the center of the fitted node.

The lines behind the picture can be removed by just filling the node (not the label) with the background color (here white). This might fail if you have a more complex graphic. (I consider it a dirty solution but sometimes they are the easiest.)

The inner sep=-.5\pgflinewidth makes the fitted node actually half the linewidth smaller as the node it's fitted to so that you don't over draw the lines that do not cross your picture. This will need to be adjusted if you use a different line width for your matrix' nodes but it can be automaticated to so that you don't have to adjust a bunch of styles just because you want to try out another line width.

Since the label and the matrix are both nodes on their own, I'd add inner sep=0pt to them, too, so that they don't contribute to the picture's bounding box.

I use the kings style to make it easy to use this without having to repeat a lot of the same TikZ instructions.

Depending on your actual graphic this might be tweaked here or there.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{fit, matrix}
\begin{document}
\begin{tikzpicture}[
    kings/.style={
      fit={#1},
      fill=white,                 % overdraw lines behind the picture
      inner sep=-.5\pgflinewidth, % but don't touch the lines around it
      node contents=,             % no text in the fitted node → no need for {}
      label={
        [inner sep=0pt]     % the label is a node, we don't want that padding here either
        center:             % the label will be placed at the center of the fitted node
        {\includegraphics[width=22mm, height=11mm]{kings}}}}]
\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
] {    
 &  &  &  &  \\
 &  &  &  &  \\
 &  &  &  &  \\
 &  &  &  &  \\
};

\node[kings=(table-2-3)(table-2-4)];
\node[kings=(table-3-1)(table-4-2)];
\end{tikzpicture}
\end{document}

Output

enter image description here

0

You must log in to answer this question.

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