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\[email protected]\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\[email protected]\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\[email protected]\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}