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

Qrrbrbirlbel
  • 119,821
lemzwerg
  • 599
  • 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. – Andrew Stacey Oct 08 '22 at 06: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 Oct 08 '22 at 06: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. – Andrew Stacey Oct 08 '22 at 07: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 Oct 08 '22 at 07:17
  • +1: Out of interest, what is the actual use case? – Dr. Manuel Kuehner Oct 08 '22 at 07:35
  • 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 Oct 08 '22 at 07:47
  • Interesting. And how would you provide the pattern data? – Dr. Manuel Kuehner Oct 09 '22 at 04:49
  • I follow the answer of https://tex.stackexchange.com/a/157127/20911 that uses `\def\pixels{...} – lemzwerg Oct 09 '22 at 17:54

2 Answers2

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

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
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.

Qrrbrbirlbel
  • 119,821