pgf-tikz / pgf

A Portable Graphic Format for TeX
https://pgf-tikz.github.io/
1.1k stars 105 forks source link

Help lines grid with coordinates #760

Closed dbitouze closed 4 years ago

dbitouze commented 4 years ago

Would be nice to provide an option that makes possible to easily add coordinates to an help lines grid, as in this answer on SE.

hmenke commented 4 years ago

Use pgfplots.

For example:

\documentclass{article}    
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        xmin=-2,xmax=5,
        ymin=-2,ymax=5,
        xtick={-2,...,5},
        ytick={-2,...,5},
        minor tick num=4,
        ticks=both,
        grid=both,
        ]

    \end{axis}
\end{tikzpicture}
\end{document}
dbitouze commented 4 years ago

Please let me explain in the following .tex file some possible use cases where pgfplots is at least overkilling and, AFAICS, doesn't help.

\documentclass{article}
\usepackage{pgfplots}
\usepackage{mwe}
\usetikzlibrary{spy}

\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}
\section{Examples with spies}
\subsection{Grid with help lines: nice but useless to locate a given point}
\begin{tikzpicture}[spy using outlines={circle, magnification=10, size=6cm, connect spies}]
  \node[inner sep=0pt] {%
    \includegraphics[width=5cm]{example-image-golden}
  };%
  \draw[help lines,step=2mm] (-3,-2) grid (3,2);
  \spy[red] on (-1.55,0) in node at (.7\textwidth,0);%
\end{tikzpicture}

\subsection{Grid with coordinates: nice and usefull to locate a given point}
\begin{tikzpicture}[spy using outlines={circle, magnification=10, size=6cm, connect spies}]
  \node[inner sep=0pt] {%
    \includegraphics[width=5cm]{example-image-golden}
  };%
  \draw (-3,-2) to[grid with coordinates] (3,2);
  \spy[red] on (-1.55,0) in node at (.7\textwidth,0);%
\end{tikzpicture}

\subsection{Grid with pgfplots axis: not handy (brain storming needed to position the node?)}
\begin{tikzpicture}[spy using outlines={circle, magnification=10, size=6cm, connect spies}]
  \begin{axis}[
    xmin=-3,xmax=3,
    ymin=-2,ymax=2,
    xtick={-3,...,3},
    ytick={-2,...,2},
    minor tick num=4,
    ticks=both,
    grid=both,
    ]
    \node[inner sep=0pt] {%
      \includegraphics[width=5cm]{example-image-golden}
    };%
    \spy[red] on (-1.55,0) in node at (.7\textwidth,0);%
  \end{axis}
\end{tikzpicture}

\section{Examples with the introductory example of TikZ documentation}
\subsection{Grid with help lines: nice but useless to locate the points}
\begin{tikzpicture}
  \draw[thick,rounded corners=8pt,red] (0,0) -- (0,2) -- (1,3.25) -- (2,2) --
  (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
  \draw[help lines,step=2mm] (-1,-1) grid (3,4);
\end{tikzpicture}

\subsection{Grid with coordinates: nice and usefull to locate the points}
\begin{tikzpicture}
  \draw[thick,rounded corners=8pt,red] (0,0) -- (0,2) -- (1,3.25) -- (2,2) --
  (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
  \draw[help lines] (-1,-1) to[grid with coordinates] (3,4);
\end{tikzpicture}

\subsection{Grid with pgfplots axis: sigh...}
\begin{tikzpicture}[spy using outlines={circle, magnification=10, size=6cm, connect spies}]
  \begin{axis}[
    xmin=-3,xmax=3,
    ymin=-2,ymax=2,
    xtick={-3,...,3},
    ytick={-2,...,2},
    minor tick num=4,
    ticks=both,
    grid=both,
    ]
    \draw[thick,rounded corners=8pt,red] (0,0) -- (0,2) -- (1,3.25) -- (2,2) --
    (2,0) -- (0,2) -- (2,2) -- (0,0) -- (2,0);
  \end{axis}
\end{tikzpicture}
\end{document}

test

hmenke commented 4 years ago

Still I believe that pgfplots covers 80% of all use-cases. If you really want to have this, encapulate it in a TikZ library and open a pull request.

dbitouze commented 4 years ago

If you really want to have this, encapsulate it in a TikZ library and open a pull request.

I'm not enough a TikZ-expert to do this in a robust way, nor in the rules of art. That's the reason I requested this feature. Hence would be nice for this feature request to not be closed.

Mo-Gul commented 4 years ago

Seeing your examples I just remembered that something similar is done to be able to add annotations to images in the tikz-imagelabels package. Maybe this is a good start to create a similar library for TikZ?

dbitouze commented 4 years ago

@Mo-Gul Many thanks for this reminder! I was aware of this package but was unable to remember its name and find it. Nevertheless:

hmenke commented 4 years ago
  • having this as a TikZ built-in feature would be nice,

Why? We already know of two packages (pgfplots, tikz-imagelabels) that implement very similar functionality. Wouldn't it be better to add the requested feature to one of these packages, rather than having yet another, slightly different, but also incomplete and incompatible implementation?

Mandatory XKCD in that context: https://xkcd.com/927/

dbitouze commented 4 years ago

We already know of two packages (pgfplots, tikz-imagelabels) that implement very similar functionality.

Mo-Gul commented 4 years ago

I have a quite simple solution for your problem using PGFPlots, which you simply didn't use right. I don't want to go into details what exactly you did wrong rather presenting the solution first which might be discussed later.

I just modified your code a bit for that.

% used PGFPlots v1.16
\documentclass{article}
\usepackage{mwe}
\usepackage{pgfplots}
    \usetikzlibrary{spy}
    \tikzset{
        % (for simplicity I created a style so one does not have to repeat the whole code over and over again)
        /tikz/my spy settings/.style={
            spy using outlines={
                circle,
                magnification=10,
                size=6cm,
                connect spies
            },
        },
        % ---
        % add a new style similar to the `grid with coordinates` style
        add grid with coordinates/.style args={%
            with xmin #1 ymin #2 and xmax #3 ymax #4%
        }{
           % draw the grid on top of everything else (at the end of the picture)
            execute at end picture={
                \begin{axis}[
                    % -----------------------------------------------------------------
                    % stuff here was added
                    % (copied from the PGFPlots manual (v1.16) section 4.26 on page 406)
                    % -----------------------------------------------------------------
                    % tell pgfplots to "grab" the axis at its
                    % internal (0,0) coord:
                    anchor=origin,
                    % tell pgfplots to place its anchor at (0,0):
                    % (This is actually the default and can
                    % be omitted)
                    at={(0pt,0pt)},
                    % tell pgfplots to use the "natural" dimensions:
                    disabledatascaling,
                    % tell pgfplots to use the same unit vectors
                    % as tikz:
                    x=1cm,y=1cm,
                    % -----------------------------------------------------------------
                    xmin=#1,xmax=#3,
                    ymin=#2,ymax=#4,
                    xtick distance=1,
                    ytick distance=1,
                    minor tick num=4,
                    ticks=both,
                    grid=both,
                    % -----------------------------------------------------------------
                    % stuff here was added as well to make the grid visible
                    % (the default grid color matches the background color of the
                    %  chosen example image)
                    grid style={black!50},
                    major grid style={very thick},
                ]
                \end{axis}
            },
        },
    }

\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}
\section{Examples with spies}

\subsection{Grid with coordinates: nice and useful to locate a given point}

\begin{tikzpicture}[my spy settings]
    \node[inner sep=0pt] {%
        \includegraphics[width=5cm]{example-image-golden}%
    };
    \draw (-3,-2) to[grid with coordinates] (3,2);
    \spy[red] on (-1.55,0) in node at (.7\textwidth,0);
\end{tikzpicture}

\subsection{Grid with pgfplots axis: not handy (brain storming needed to position the node?)}

\begin{tikzpicture}[
    my spy settings,
    add grid with coordinates={with xmin -3 ymin -2 and xmax 3 ymax 2},
]
    \node[inner sep=0pt] {%
        \includegraphics[width=5cm]{example-image-golden}%
    };
    \spy[red] on (-1.55,0) in node at (.7\textwidth,0);
\end{tikzpicture}

\end{document}

which results in

image showing the result of above code

dbitouze commented 4 years ago

Very nice solution indeed, which could be subject to a library! Except maybe that loading pgfplots just for this is a bit overkilling, isn't it?

hmenke commented 4 years ago

I have reopened this issue and applied the “help wanted” tag to show that if you want this feature, you (or someone else) will have to implement this.

dbitouze commented 4 years ago

@tallmarmot:

It would be interesting to know what kind of ticks you have in mind.

What I have in mind is the grids as provided by PSTricks (often temporary used), which are very useful when one creates a draw:

\documentclass{article}
\usepackage{pstricks}
\thispagestyle{empty}
\begin{document}
\psgrid(0,0)(-1,-1)(3,2)
\end{document}

test

hmenke commented 4 years ago

@dbitouze Looks like you have a solution already. Just place that in a node at the origin and you're good to go.

\documentclass{article}
\usepackage{pstricks}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    \node at (0,0) {\psgrid(0,0)(-1,-1)(3,2)};
    \draw[thick,red] (0,0) to (2,2);
\end{tikzpicture}
\end{document}

test

dbitouze commented 4 years ago

@hmenke That's not a suitable solution: loading pstricks just for a grid is overkilling and, above all, this would make impossible to compile with pdftex or luatex engines (unless using the not very handy auto-pst-pdf package and run with the -shell-escape option).

hmenke commented 4 years ago

Well, we have proposed multiple disparate solutions, none of which you have deemed satisfactory. Also, no volunteers are forthcoming for the library implementation that you demand. The lack of interest from the community in this feature led me to close this request.

Further, in my opinion, PGF/TikZ should not provide any pre-made solutions. Instead, I think of it as a toolbox with generic mechanisms that allow the user to create specific solutions like this one.

dbitouze commented 4 years ago

led me to close this request.

Too bad!

Further, in my opinion, PGF/TikZ should not provide any pre-made solutions. Instead, I think of it as a toolbox with generic mechanisms that allow the user to create specific solutions like this one.

Doesn't TikZ provide the pre-made grid path and the help lines style? IMO, they only lack the grid labels that let the user immediately know which are the coordinates of a given point of the grid.

hmenke commented 4 years ago

Yes, indeed TikZ provides grid and help lines as the tools and leaves it to the user to combine them into specific solutions, such as the one you wish.

dbitouze commented 4 years ago

Sorry to insist. IMO, grids with labels are not that specific. Comparatively, PSTricks considers grids with labels as basic graphics objects.

hmenke commented 4 years ago

Then use PSTricks.

dbitouze commented 4 years ago

If I insist, it is because I do prefer TikZ over PSTricks nowadays: much more possibilities and, above all, it does work with all the current engines. My request is just a feature request, no need to be rude.

dbitouze commented 4 years ago

OK, sorry: not rude but rather blunt :)

What is inconvenient IMO is that help lines often are only partially helpful. In the following example (randomly selected), as in many of the documentation's ones, one has to check the code in order to figure out where is the point (0,0) (and that's worse if (0,0) is in the middle of the grid): test

By contrast, the following picture would be immediately understood. test

And, when one has to build a complex picture, with many points, the labels would be helpful in order to position them. OK, I know TikZ provides the relative positions of the nodes but, anyway.

Code of the second figure

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[help lines] (0,0) grid (3,2);
\draw
(0,0) -- (1,1) -- (1,0);
\draw[scale=2,blue]
(0,0) -- (1,1) -- (1,0);
\draw[scale around={2:(1,1)},red] (0,0) -- (1,1) -- (1,0);
% Grid labels added
\foreach \pos in {0,1,2,3}
\draw[shift={(\pos,0)}] (0pt,2pt) -- (0pt,-2pt) node[below] {$\pos$};
\foreach \pos in {0,1,2}
\draw[shift={(0,\pos)}] (2pt,0pt) -- (-2pt,0pt) node[left] {$\pos$};
\end{tikzpicture}
\end{document}