3

I have a pixel grid consisting of dashed lines, and I want to set a pixel using minimum size.

As can be seen, I set the minimum size manually, which works. However, I would like to set it to another, inherited style key. How can I do that? The (naive) commented-out code doesn't work.

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

\usetikzlibrary{calc}

\tikzset{
  grid lines/.style={
    line width=0.5pt,
    dashed,
    step=5mm},
  pixel/.style={
    grid lines,
    solid,
    draw,
%   minimum size=\pgfkeysvalueof{step},
    minimum size=5mm,
    fill}
}

\begin{document}
\begin{tikzpicture}
  \draw[grid lines] (0,0) grid (1,1);
  \node[pixel] at (0.25,0.25) {};
\end{tikzpicture}
\end{document}

mwe

8
  • If you draw it as well as filling it then it will naturally expand by half the line width, which should be the right amount to cover the dashes. Commented Oct 8, 2022 at 6:52
  • OK, I could inherit the line width property from grid lines. However, how can I assign the grid lines/step property to pixel/minimum size? I've now simplified the question.
    – lemzwerg
    Commented Oct 8, 2022 at 6:59
  • Simplest way is to have keys that save those details, say pixel/line width and pixel/size which then the grid lines and pixel styles use. So rather than try to read from a separate style, you effectively have a "parent" style that sets both. Commented Oct 8, 2022 at 7:11
  • Well, yes. There are a lot of practical solutions; for example, I could do \def\gridStep{5mm} and use this value in both styles. Still, this is far from elegant IMHO. The right way would really be assign one key value to another key, and I wonder how this can be done – actually, I can't believe that I'm the first person who wants to do something along this way...
    – lemzwerg
    Commented Oct 8, 2022 at 7:17
  • 1
    The actual use-case is to draw a simple, magnified bitmap (for example, the letter 'A' at a size of 12px) for documentation purposes.
    – lemzwerg
    Commented Oct 8, 2022 at 7:47

2 Answers 2

3

It is possible to dig into the code to see how step works and read back the magic numbers (\tikz@grid@x and \tikz@grid@y) but I'd recommend a different approach in which you set those parameters using separate keys which you then use in both pieces.

\documentclass[tikz, border=3mm]{standalone}
%\url{https://tex.stackexchange.com/q/660910/86}
\usetikzlibrary{calc}

\tikzset{
  pixel/line width/.initial=0.5pt,
  pixel/size/.initial=5mm,
  grid lines/.style={
    line width=\pgfkeysvalueof{/tikz/pixel/line width},
    dashed,
    step=\pgfkeysvalueof{/tikz/pixel/size}
  },
  pixel/.style={
    solid,
    draw,
    line width=\pgfkeysvalueof{/tikz/pixel/size},
    minimum size=\pgfkeysvalueof{/tikz/pixel/line width},
    inner sep=0pt,
    fill}
}

\begin{document}
\begin{tikzpicture}
  \draw[grid lines] (0,0) grid (1,1);
  \node[pixel] at (0.25,0.25) {};
\end{tikzpicture}
\end{document}

grid with filled in square

4
  • Aaah, thanks! Yes, this looks very nice.
    – lemzwerg
    Commented Oct 8, 2022 at 7:23
  • +1: First time I see .is family Commented Oct 8, 2022 at 7:35
  • @Dr.ManuelKuehner Too bad its effect will be overwritten by pixel/.style. (pixel/.is family is a shortcut to a faster version of pixel/.style={/tikz/pixel/.cd}.) Commented Oct 8, 2022 at 14:07
  • 1
    I get in the habit of using .is family whenever I define a sub-family of keys. I'll remove it as it is redundant here. Commented Oct 8, 2022 at 14:22
2

The \pgfkeysvalueof macro only works with actual value-keys.

Due to, I guess, legacy reasons, the keys xstep and ystep just define another macro (here \tikz@grid@x and \tikz@grid@y) even though they could as well have been value-keys.

And step just sets these two macros to the same value? No, because it also allows a value in the form of a coordinate (starting with () and sets the xstep to that coordinate's x value and the ystep to that coordinate's y value.

Even if we find a way to retrieve the value that has been given to one of these keys, one needs to think about how to deal with step = (15:1cm).


Well, you can always add more stuff to an already existing key, say,

@step/.initial=1cm,
step/.append style={/tikz/@step={#1}}

and then \pgfkeysvalueof{/tikz/@step} returns the value that was given to step last (which might as well have been (15:1cm)!).


We could re-write how xstep, ystep and step work:

\tikzset{
  xstep/.initial=1cm,
  ystep/.initial=1cm,
}
\makeatletter
\def\tikz@step@single#1{%
  \pgfkeyssetvalue{/tikz/xstep}{#1}%
  \pgfkeyssetvalue{/tikz/ystep}{#1}}
\def\tikz@step@point#1{%
  \pgf@process{#1}%
  \pgfkeyssetevalue{/tikz/xstep}{\the\pgf@x}%
  \pgfkeyssetevalue{/tikz/ystep}{\the\pgf@y}}
\def\tikz@grid@x{\pgfkeysvalueof{/tikz/xstep}}
\def\tikz@grid@y{\pgfkeysvalueof{/tikz/ystep}}
\makeatother

and now you can use \pgfkeysvalueof{/tikz/xstep}/\pgfkeysvalueof{/tikz/ystep}
but then you still have the case of step = 1 since TikZ allows dimension-less units to be used with the xy coordinate system. (Dimension-less units in minimum size will be interpreted as pt.)

In your case, you are explicitly using step=5mm and putting grid lines inside pixel so you're side-stepping all these problems but I want to highlight how complex this can get when you factor in all general possibilities and use cases.


All that to say that Andrew Stacey's solution is a much cleaner way to this and give you (or your users) much better control over what gets drawn. Just don't forget to use only dimensions with units for pixel/size.

1
  • Thanks! I miss such comments in the TikZ manual...
    – lemzwerg
    Commented Oct 8, 2022 at 15:36

You must log in to answer this question.

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