5

I have a question about the coordinates in tikz: when I set the style of a node by shift={(1, 1)}, what happens and how are the coordinates parsed into corresponding offset applied to each point of the graph to be drawn?

And if I want to define a pgfkey with a coordinate-like parameter so that when I pass a string like (2, 3, 4), it is parsed and the values are saved to three macros respectively, is it feasible to imitate the way how tikz handles or are there some other convenient methods?

  • 1
    shift={(1, 1)} is parsed as "shift by 1*e_1 + 1*e_2", where e_1 and e_2 are the units vectors. This is different fromshift={(1cm, 1cm)}, which produces a shift by 1cm in x direction and 1cm in y directions. In the default setting, e_1=(1cm,0) and e_2=(0,1cm), so both "accidentally" yield the same result. It is really instructive to read tex.stackexchange.com/a/31606/194703 for that. tikz also parses and interprets the coordinates in terms of some dimensions that specify their location in screen coordinates in pt. – Schrödinger's cat Nov 18 at 5:06
  • 2
    The string that generates the coordinate is, in some situations, stored in \csname tikz@dcl@coord@#1\endcsname, where #1 is the name of the coordinate. This happens if you use e.g. \path (2,3,4) coordinate (A);, then \tikz@dcl@coord@A is (2,3,4). This has been used in github.com/tallmarmot/pgf/tree/master/experiments/Marmot/… to allow TikZ to store 3D coordinates, and use them for vector operations. – Schrödinger's cat Nov 18 at 5:12
  • 1
    Just what I want! And thanks for providing the link again. – ZhiyuanLck Nov 18 at 5:22
9

We can disentangle what is going on at the low level. First of all, shift is defined as

\tikzoption{shift}{\tikz@addtransform{\tikz@scan@one@point\pgftransformshift#1\relax}}%

The macro that does the heavy lifting scanning a point is \tikz@scan@one@point. The result is a \pgfpoint which is then passed to \pgftransformshift. This transformation is then added to the stack of transformations which is managed by \tikz@addtransform.

The procedure of \tikz@scan@one@point is a bit more tricky. Here is a tree diagram of what happens inside approximately.

                         \tikz@scan@one@point
                                   |
                         if next character is +
                        /yes                 no\
                scan relative point             |
                       |                        |
             if next character is +             |
             /yes                no\            |
  relative to previous       relative to first  |
             \                     /            |
               scan absolute point --------------
                       |
                if character is (
               /yes            no\
              |           expand tokens (at most 100 times)
              |                  |
              |            valid coordinate found?
              |           /yes                  no\
              |          |                    Give up.
              |          |           "Cannot parse this coordinate"
              |          |
              -- if next character is [
                /yes                 no\
scan until ] and pass to \tikzset       |
               \                       /
                 if next character is $
                /yes                 no\
     <--- calc library                 |
                          if coordinate contains with cs:
                         /yes                          no\
                parse coordinate system                   |
                                          if coordinate contains intersection
                                         /yes                              no\
                                parse intersection              if coordinate contains with |
                                                               /yes                        no\
                                                    if coordinate contains -|                 |
                                                   /yes                    no\                |
                                          parse -| specifier      parse |- specifier          |
                                                                                              |
                                                                                   if coordinate contains :
                                                                                  /yes                   no\
                                                                        parse polar coordinate             |
                                                                                                if coordinate contains ,
                                                                                               /yes                   no\
                                                                                    parse regular coordinate     parse node name

In your case it will descend into the parse regular coordinate branch, where the point will just be split at the comma and each component will be evaluated with \pgfmathparse.

Regarding the second part of your question:

And if I want to define a pgfkey with a coordinate-like parameter so that when I pass a string like (2, 3, 4), it is parsed and the values are saved to three macros respectively, is it feasible to imitate the way how tikz handles or are there some other convenient methods?

In this case I think you are better off parsing this by hand, i.e. something along those lines:

\tikzset{
  triple/x/.store in=\triplex,
  triple/y/.store in=\tripley,
  triple/z/.store in=\triplez,
  triple/.style args={(#1,#2,#3)}{
    triple/x=#1,
    triple/y=#2,
    triple/z=#3,
  }
}

\tikzset{triple={(1,2,3)}}
3

shift={(1, 1)} is parsed as

shift by 1*e_1 + 1*e_2 ,

where e_1 and e_2 are the units vectors. This is different from shift={(1cm, 1cm)}, which produces a shift by 1cm in x direction and 1cm in y directions. In the default setting, e_1=(1cm,0) and e_2=(0,1cm), so both "accidentally" yield the same result. It is really instructive to read this nice answer for that. TikZ also parses and interprets the coordinates in terms of some dimensions that specify their location in screen coordinates in pt.

TikZ does, under some circumstances, store the string that was used to define the coordinate. It works for the

\path (<coord>) coordinate (<A>);

syntax.

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\path (2,3,4) coordinate (A) (5,1) coordinate (B);
\coordinate (C) at (5,4,3);
\end{tikzpicture}

\makeatletter
$(A)=\tikz@dcl@coord@A$

$(B)=\tikz@dcl@coord@B$

$(C)=\tikz@dcl@coord@C$
\makeatother
\end{document}

enter image description here

The example also shows that the syntax

\coordinate (C) at (5,4,3);

does not (yet?) work.

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.