14

As in here, the code

\draw[step=0.5cm,color=gray] (-1,-1) grid (1,1);

gives me a nice finite 4x4 grid. But when I choose a different starting point, like

\draw[step=0.5cm,color=gray] (2,2) grid (4,4);

then the left and the bottom border of the grid disappears. What is the problem and how can I fix it so that I have all the borders? I know I can draw a rectangle there, but I assume there is some cleaner solution.

  • Nice question! I added the word "missing" to your title to make it a bit clearer, is that OK? – Hendrik Vogt Mar 19 '11 at 15:56
15

In the pgfmanual it says on p. 145 that

due to rounding errors, the "last" lines of a grid may be omitted. In this case, you have to add an epsilon to the corner points

In this case, you will have to subtract an epsilon, i.e. a very small value, from the corner point. Something like

\draw[step=0.5cm,color=gray] (2-0.001,2-0.001) grid (4,4);

will work without any visible artefacts.

1

In the pgfmanual, we can read "Note that due to rounding errors, the “last” lines of a grid may be omitted." More precisely, the first lines may be omitted because for the "last" ones, there is a test in the algorithm to recover these lines in the macro \pgf@pathgrid

\advance\pgf@y by-0.01pt\relax%
\ifdim\pgf@y<\pgf@yb%

For example the next code draws all the lines

\begin{tikzpicture} 
\draw[step=.5cm,color=gray] (2,2) grid (3.9999,3.9999);
  \draw[fill=red](0,0) circle (1pt);  
\end{tikzpicture}

An idea to avoid the problem described by the OP, is to modify the macro and to add a test for the first lines : I used \pgf@xx and \pgf@yy I think that it's not a big problem. The "rounding problem" begins with the next lines

  \pgf@yy=\pgf@ya\relax% added
  \advance\pgf@yy-0.01pt\relax% added 
  \ifdim\pgf@y<\pgf@yy% modified 
    \advance\pgf@y by\pgf@yc%
  \fi%

The complete code is

\documentclass{minimal}
\usepackage{tikz}

\makeatletter
\pgfkeys{
  /pgf/stepx/.initial=1cm,
  /pgf/stepy/.initial=1cm,
  /pgf/step/.code={\pgf@process{#1}\pgfkeysalso{/pgf/stepx/.expanded=\the\pgf@x,/pgf/stepy/.expanded=\the\pgf@y}},
  /pgf/step/.value required
}

\def\pgfpathgrid{\pgfutil@ifnextchar[{\pgf@pathgrid}{\pgf@pathgrid[]}}
\def\pgf@pathgrid[#1]#2#3{%
  \pgfset{#1}%
  \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/stepx}}%
  \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/stepy}}%
  \pgf@process{#3}%
  \pgf@xb=\pgf@x%
  \pgf@yb=\pgf@y%
  \pgf@process{#2}%
  \pgf@xa=\pgf@x\relax%
  \pgf@ya=\pgf@y\relax%
  {%
    % compute bounding box
    % first corner
    \pgf@x=\pgf@xb%
    \pgf@y=\pgf@yb%
    \pgf@pos@transform{\pgf@x}{\pgf@y}%
    \pgf@protocolsizes{\pgf@x}{\pgf@y}%
    % second corner
    \pgf@x=\pgf@xb%
    \pgf@y=\pgf@ya%
    \pgf@pos@transform{\pgf@x}{\pgf@y}%
    \pgf@protocolsizes{\pgf@x}{\pgf@y}%
    % third corner
    \pgf@x=\pgf@xa%
    \pgf@y=\pgf@yb%
    \pgf@pos@transform{\pgf@x}{\pgf@y}%
    \pgf@protocolsizes{\pgf@x}{\pgf@y}%
    % fourth corner
    \pgf@x=\pgf@xa%
    \pgf@y=\pgf@ya%
    \pgf@pos@transform{\pgf@x}{\pgf@y}%
    \pgf@protocolsizes{\pgf@x}{\pgf@y}%
  }%
  \c@pgf@counta=\pgf@y\relax%
  \c@pgf@countb=\pgf@yc\relax%
  \divide\c@pgf@counta by\c@pgf@countb\relax% rounding problem begins here
  \pgf@y=\c@pgf@counta\pgf@yc\relax% 
  \pgf@yy=\pgf@ya\relax% added
  \advance\pgf@yy-0.01pt\relax% added 
  \ifdim\pgf@y<\pgf@yy% modified the problem appears here !!
    \advance\pgf@y by\pgf@yc%
  \fi%
  \loop% horizontal lines
    {%
      \pgf@xa=\pgf@x%
      \pgf@ya=\pgf@y%
      \pgf@pos@transform{\pgf@xa}{\pgf@ya}
      \pgfsyssoftpath@moveto{\the\pgf@xa}{\the\pgf@ya}%
      \pgf@xa=\pgf@xb%
      \pgf@ya=\pgf@y%
      \pgf@pos@transform{\pgf@xa}{\pgf@ya}
      \pgfsyssoftpath@lineto{\the\pgf@xa}{\the\pgf@ya}%
    }%
    \advance\pgf@y by\pgf@yc%
  \ifdim\pgf@y<\pgf@yb%
  \repeat%
  \advance\pgf@y by-0.01pt\relax%
  \ifdim\pgf@y<\pgf@yb%
    {%
      \pgf@xa=\pgf@x%
      \pgf@ya=\pgf@y%
      \pgf@pos@transform{\pgf@xa}{\pgf@ya}
      \pgfsyssoftpath@moveto{\the\pgf@xa}{\the\pgf@ya}%
      \pgf@xa=\pgf@xb%
      \pgf@ya=\pgf@y%
      \pgf@pos@transform{\pgf@xa}{\pgf@ya}
      \pgfsyssoftpath@lineto{\the\pgf@xa}{\the\pgf@ya}%
    }%
  \fi%
  \c@pgf@counta=\pgf@x\relax%
  \c@pgf@countb=\pgf@xc\relax%
  \divide\c@pgf@counta by\c@pgf@countb\relax%
  \pgf@x=\c@pgf@counta\pgf@xc\relax%
  \pgf@xx=\pgf@xa\relax% added 
  \advance\pgf@xx-0.01pt\relax% added 
  \ifdim\pgf@x<\pgf@xx% modified, 
    \advance\pgf@x by\pgf@xc%
  \fi%
  \loop% vertical lines
    {%
      \pgf@xc=\pgf@x%
      \pgf@yc=\pgf@ya%
      \pgf@pos@transform{\pgf@xc}{\pgf@yc}
      \pgfsyssoftpath@moveto{\the\pgf@xc}{\the\pgf@yc}%
      \pgf@xc=\pgf@x%
      \pgf@yc=\pgf@yb%
      \pgf@pos@transform{\pgf@xc}{\pgf@yc}
      \pgfsyssoftpath@lineto{\the\pgf@xc}{\the\pgf@yc}%
    }%
    \advance\pgf@x by\pgf@xc%
  \ifdim\pgf@x<\pgf@xb%
  \repeat%
  \advance\pgf@x by-0.01pt\relax%
  \ifdim\pgf@x<\pgf@xb%
    {%
      \pgf@xc=\pgf@x%
      \pgf@yc=\pgf@ya%
      \pgf@pos@transform{\pgf@xc}{\pgf@yc}
      \pgfsyssoftpath@moveto{\the\pgf@xc}{\the\pgf@yc}%
      \pgf@xc=\pgf@x%
      \pgf@yc=\pgf@yb%
      \pgf@pos@transform{\pgf@xc}{\pgf@yc}
      \pgfsyssoftpath@lineto{\the\pgf@xc}{\the\pgf@yc}%
    }%
  \fi%
}
 \makeatother
\begin{document}


\begin{tikzpicture} 
\draw[step=.5cm,color=gray] (2,2) grid (4,4);
\draw[fill=red](4,4) circle (1pt); 
\end{tikzpicture}    


\begin{tikzpicture}

\draw[step=0.3cm,color=gray] (0,0) grid (1,1);
    \draw[red](0,0)--(1,1);        
  \draw[fill=red](0,0) circle (1pt);  
\end{tikzpicture} 
\begin{tikzpicture}
\draw[step=0.3cm,color=gray] (1,1) grid (2,2);
  \draw[red](1,1)--(2,2); 
    \draw[fill=red](1,1) circle (1pt);        
\end{tikzpicture}     
\end{document}

Now the pgfmanual before discribes the rounding problem, gives : "It is important to note that the grid is always “phased” such that it contains the point (0, 0) if that point happens to be inside the rectangle. Thus, the grid does not always have an intersection at the corner points; this occurs only if the corner points are multiples of the stepping."

So if we examine the code, we can see that if you want the first lines of the grid at the intersection of the corner point (left down), the possibility is to draw a grid from the (0,0) corner and then to move the grid

\begin{tikzpicture} 
  \draw[step=0.5cm,shift={(2,2)}] (0,0) grid (2,2);
\end{tikzpicture}

You can compare

\begin{tikzpicture} 
  \draw[step=0.3cm,shift={(1,1)}] (0,0) grid (1,1);
\end{tikzpicture}

with

\begin{tikzpicture} 
  \draw[step=0.3cm] (1,1) grid (2,2);
\end{tikzpicture}
  • @Altermundus: I follow the advice from the author. Although I think he should deal with the rounding errors, not the user. – Adam Trhon Mar 20 '11 at 9:03
  • @Dadam : You are right and you can choice what you want. I only give an idea about your problem and I think it's possible to find a better algorithm. – Alain Matthes Mar 20 '11 at 10:39
  • @Altermundus: And I like that idea. It made me look closer at the grids, realizing that they are little bit more tricky ([step=0.3cm](0, 0) grid (1, 1) doesn't give the same result as [step=0.3] (1, 1) grid (2, 2)) and for drawing C arrays, I should consider using table instead of grid. – Adam Trhon Mar 20 '11 at 11:32
  • @Dadam You need to write \tikz\draw[step=0.3333cm] (0, 0) grid (1, 1); 0.3333in the two codes, If you want the same result (except for the last lines). This is why I write : " because in some cases, it's not possible to add an epsilon!" . In my packages, I define a macro \grid and I made calculus with fp. I know that the code is slower and I don't respect TikZ syntax but ...it's necessary to find a solution – Alain Matthes Mar 20 '11 at 11:52
  • @Altermundus: But I want [step=0.3cm], not [step=0.3333cm](I would recommend [step=1.0/3]). What I mentioned above is not a bug, it's a feature: according to the pgfmanual, the grid always starts at (0, 0) and is clipped to the rectangle - theoretically. In practice, the boundaries of lines are calculated - and that is the spot where rounding errors occure, I think. – Adam Trhon Mar 20 '11 at 12:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.