# How can I show coordinates by grid in TikZ automatically?

I have the following TikZ code which draws a grid and shows the coordinates. To display the coordinates I am using the loop foreach.

\documentclass[12pt]{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw[help lines,step=.2] (-2,-2) grid (7,4);
\draw[help lines,line width=.6pt,step=1] (-2,-2) grid (7,4);
\foreach \x in {-2,-1,0,1,2,3,4,5,6,7}
\node[anchor=north] at (\x,-2) {\x};
\foreach \y in {-2,-1,0,1,2,3,4}
\node[anchor=east] at (-2,\y) {\y};
\end{tikzpicture}
\end{document}


Is there a way do simplify the code in this way that I have a key like show coordinates (maybe step coordinates/.initial=step ):

\draw[help lines,step=.2,show coordinates=true] (-2,-2) grid (7,4);


Or a modification of the command grid like

\draw[help lines,step=.5] (-2,-2) gridwithcoordinates (7,4);


By using pstricks it is very simple with the command \psgrid

\documentclass[12pt]{article}
\usepackage{pstricks}

\begin{document}
\begin{pspicture}(-2,-2)(7,4)
\psgrid
\end{pspicture}
\end{document}


Bonus: How can I set a larger line width for the help lines at the integer coordinates (see picture above)?

(I don't know the correct words ;-) )

-
Maybe this is a nice idea for a new package ala tikz-grid. –  Marco Daniel Dec 29 '11 at 11:02
@TorbjørnT.: Why do you think best-practice isn't the correct tag? –  Marco Daniel Dec 29 '11 at 12:56
Forgive me, I should have added a comment. I thought that this is a question of the type "is there an easier way of doing this", rather than "what is the preferred way of accomplishing this". The latter is the kind of question I would put that tag on. If you (or anyone else) feel that I'm wrong about this, don't hesitate to add it back in. –  Torbjørn T. Dec 29 '11 at 13:27
I added the code to change the line widths. –  Marc van Dongen Dec 29 '11 at 13:39
Check this site michaelgoerz.net/blog/2009/07/… –  user10364 Dec 30 '11 at 15:42

Here's a solution that uses to paths to execute arbitrary code in the guise of a simple command. If the preamble were hidden away in a package, the invocation would just be:

\begin{tikzpicture}
\draw (-2,-2) to[grid with coordinates] (7,4);
\end{tikzpicture}


The sneaky trick is to use the fact that the to path declaration can contain arbitrary code via a \pgfextra command. With that, it's just a matter of grabbing the starting and ending coordinates (which are encoded as \tikztostart and \tikztotarget) and then using your original code (which I assume you were reasonably happy with) as the code to be executed.

With the preamble, the code is:

\documentclass{article}
%\url{}
\usepackage{tikz}

\makeatletter
\def\grd@save@target#1{%
\def\grd@target{#1}}
\def\grd@save@start#1{%
\def\grd@start{#1}}
\tikzset{
grid with coordinates/.style={
to path={%
\pgfextra{%
\edef\grd@@target{(\tikztotarget)}%
\tikz@scan@one@point\grd@save@target\grd@@target\relax
\edef\grd@@start{(\tikztostart)}%
\tikz@scan@one@point\grd@save@start\grd@@start\relax
\draw[minor help lines] (\tikztostart) grid (\tikztotarget);
\draw[major help lines] (\tikztostart) grid (\tikztotarget);
\grd@start
\pgfmathsetmacro{\grd@xa}{\the\pgf@x/1cm}
\pgfmathsetmacro{\grd@ya}{\the\pgf@y/1cm}
\grd@target
\pgfmathsetmacro{\grd@xb}{\the\pgf@x/1cm}
\pgfmathsetmacro{\grd@yb}{\the\pgf@y/1cm}
\pgfmathsetmacro{\grd@xc}{\grd@xa + \pgfkeysvalueof{/tikz/grid with coordinates/major step}}
\pgfmathsetmacro{\grd@yc}{\grd@ya + \pgfkeysvalueof{/tikz/grid with coordinates/major step}}
\foreach \x in {\grd@xa,\grd@xc,...,\grd@xb}
\node[anchor=north] at (\x,\grd@ya) {\pgfmathprintnumber{\x}};
\foreach \y in {\grd@ya,\grd@yc,...,\grd@yb}
\node[anchor=east] at (\grd@xa,\y) {\pgfmathprintnumber{\y}};
}
}
},
minor help lines/.style={
help lines,
step=\pgfkeysvalueof{/tikz/grid with coordinates/minor step}
},
major help lines/.style={
help lines,
line width=\pgfkeysvalueof{/tikz/grid with coordinates/major line width},
step=\pgfkeysvalueof{/tikz/grid with coordinates/major step}
},
grid with coordinates/.cd,
minor step/.initial=.2,
major step/.initial=1,
major line width/.initial=2pt,
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw[help lines,step=.2] (-2,-2) grid (7,4);
\draw[help lines,line width=.6pt,step=1] (-2,-2) grid (7,4);
\foreach \x in {-2,-1,0,1,2,3,4,5,6,7}
\node[anchor=north] at (\x,-2) {\x};
\foreach \y in {-2,-1,0,1,2,3,4}
\node[anchor=east] at (-2,\y) {\y};
\end{tikzpicture}

\begin{tikzpicture}
\draw (-2,-2) to[grid with coordinates] (7,4);
\end{tikzpicture}
\end{document}


(Your original grid is included first for comparison. I thickened the major lines on my version, by the way.)

The extra bits, and the stuff with the @s, is for processing the coordinates to figure out where to start and end the labelling. The assumption is that we start at the first coordinate and work our way up according to the major step separation to the second coordinate. So we need to process these coordinates to extract that information. This means that the coordinates to the command can be any TikZ coordinate: we use \tikz@scan@one@point which is how TikZ itself parses coordinates.

One thing to note is the use of \pgfmathprintnumber to ensure that the labels are printed nicely.

The result is as follows:

-
Wow. Very nice solution. –  cjorssen Dec 30 '11 at 22:07
++++1 -- awesome. Will you create an extra library for CTAN? –  Marco Daniel Dec 30 '11 at 22:08
Nice. I have to study this solution. My initial idea was to use to paths but I thought that it wasn't possible to change the pen style. One suggestion: change the line cap to round. –  Marc van Dongen Dec 30 '11 at 22:50
Awesome Andrew! :) –  Paulo Cereda Dec 31 '11 at 10:30
@MarcvanDongen: Good idea. Have you tested that? If so, feel free to edit accordingly - might be a day or so before I get round to testing it. –  Loop Space Dec 31 '11 at 17:21

Not exactly what you are looking for (no subgrid) but coordinates are shown.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\makeatletter
\def\tikz@Get@x@coor#1,#2\tikz@sentinel{%
\pgfmathparse{int(round(#1/1cm))}}
\def\tikz@Get@y@coor#1,#2\tikz@sentinel{%
\pgfmathparse{int(round(#2/1cm))}}
\tikzset{%
show grid integer coordinates/.style = {%
decoration = {%
show path construction,
moveto code = {%
\expandafter\tikz@Get@x@coor\tikzinputsegmentfirst\tikz@sentinel
\edef\tikz@tempa{\pgfmathresult}%
\expandafter\tikz@Get@x@coor\tikzinputsegmentlast\tikz@sentinel
\edef\tikz@tempb{\pgfmathresult}%
\pgfmathparse{equal(\tikz@tempa,\tikz@tempb)}%
\ifnum\pgfmathresult=1\relax
\node[anchor=north] at (\tikzinputsegmentfirst) {%
\tikz@tempa};
\else
\node[anchor=east] at (\tikzinputsegmentfirst) {%
\expandafter\tikz@Get@y@coor\tikzinputsegmentfirst\tikz@sentinel
\pgfmathresult};
\fi}},
postaction = decorate}}
\begin{document}
\begin{tikzpicture}
\draw[show grid integer coordinates] (-2,2) grid (7,4);
\end{tikzpicture}
\end{document}


The subgrid can be added with the same idea, but it goes too far... I don't know how to access to the upper right corner x coordinate: \tikz@lastx is set to 0.0pt inside the moveto code.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing,calc}
\makeatletter
\def\tikz@Get@x@coor#1,#2\tikz@sentinel{%
\pgfmathparse{int(round(#1/1cm))}}
\def\tikz@Get@y@coor#1,#2\tikz@sentinel{%
\pgfmathparse{int(round(#2/1cm))}}
\tikzset{%
show grid integer coordinates/.style = {%
preaction = {%
decoration = {%
show path construction,
moveto code = {%
\expandafter\tikz@Get@x@coor\tikzinputsegmentfirst\tikz@sentinel
\edef\tikz@tempa{\pgfmathresult}%
\expandafter\tikz@Get@x@coor\tikzinputsegmentlast\tikz@sentinel
\edef\tikz@tempb{\pgfmathresult}%
\pgfmathparse{equal(\tikz@tempa,\tikz@tempb)}%
\ifnum\pgfmathresult=1\relax
\node[anchor=north] at (\tikzinputsegmentfirst) {%
\tikz@tempa};
\draw[help lines,step=.1] (\tikzinputsegmentfirst) grid
($(\tikzinputsegmentlast)+(1,0)$);
\else
\node[anchor=east] at (\tikzinputsegmentfirst) {%
\expandafter\tikz@Get@y@coor\tikzinputsegmentfirst\tikz@sentinel\pgfmathresult};
\fi}},
decorate}}}
\begin{document}
\begin{tikzpicture}
\draw[show grid integer coordinates] (-2,2) grid (7,4);
\end{tikzpicture}
\end{document}

-
+1 Nice idea ;-) –  Marco Daniel Dec 30 '11 at 14:35

I am sorry but there's no easy solution. First I tried using a to path but that doesn't let you change the line style:-( Next I tried implementing a dedicated command. This time the main problem is that in order to iterate over the coordinate labels, the labels should be integral, which isn't true in general. The following should work, but it requires coordinates consisting of two integers each; rationals and labels are not allowed. It should be possible to implement a macro that takes more general arguments but that would take too long.

\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\newif\ifmygrid@coordinates
\tikzset{/mygrid/step line/.style={line width=0.80pt,draw=gray!80},
/mygrid/steplet line/.style={line width=0.25pt,draw=gray!80}}
\pgfkeys{/mygrid/.cd,
step/.store in=\mygrid@step,
steplet/.store in=\mygrid@steplet,
coordinates/.is if=mygrid@coordinates}
\def\mygrid@def@coordinates(#1,#2)(#3,#4){%
\def\mygrid@xlo{#1}%
\def\mygrid@xhi{#3}%
\def\mygrid@ylo{#2}%
\def\mygrid@yhi{#4}%
}
\newcommand\DrawGrid[3][]{%
\pgfkeys{/mygrid/.cd,coordinates=true,step=1,steplet=0.2,#1}%
\draw[/mygrid/steplet line] #2 grid[step=\mygrid@steplet] #3;
\draw[/mygrid/step line] #2 grid[step=\mygrid@step] #3;
\mygrid@def@coordinates#2#3%
\ifmygrid@coordinates%
\draw[/mygrid/step line]
\foreach \xpos in {\mygrid@xlo,...,\mygrid@xhi} {%
(\xpos,\mygrid@ylo) -- ++(0,-3pt)
node[anchor=north] {$\xpos$}
}
\foreach \ypos in {\mygrid@ylo,...,\mygrid@yhi} {%
(\mygrid@xlo,\ypos) -- ++(-3pt,0)
node[anchor=east] {$\ypos$}
};
\fi%
}
\makeatother

\begin{document}
\begin{tikzpicture}
\DrawGrid{(-2,-1)}{(3,2)}
%\DrawGrid[coordinates=false]{(-2,-1)}{(3,2)}
\end{tikzpicture}
\end{document}

-
+1 Thanks for the work and the first inspiration. –  Marco Daniel Dec 29 '11 at 13:13