# TikZ angle calculation and rotation with transformed coordinates

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

\begin{document}

\typeout{Using internal functions}
\begin{tikzpicture}[
color=green!50!black]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) to (2,2) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\pgfmathanglebetweenpoints{(\tikztostart)}{(\tikztotarget)}\xdef\aaa{\pgfmathresult}};
\node [draw] at (1,1) {\aaa}; % shouldn't be 45?
\end{tikzpicture}
\typeout{Using coordinates}
\begin{tikzpicture}[
color=blue]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\pgfmathanglebetweenpoints{\pgfpointanchor{a}{center}}{\pgfpointanchor{b}{center}}\xdef\aaa{\pgfmathresult}};
\node [draw, rotate=\aaa] at (1,1) {\aaa}; % Ok, now it's 45
\end{tikzpicture}
\typeout{Using coordinates and scaling}
\begin{tikzpicture}[
color=red, xscale=2
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\pgfmathanglebetweenpoints{\pgfpointanchor{a}{center}}{\pgfpointanchor{b}{center}}\xdef\aaa{\pgfmathresult}};
\node [draw, rotate=\aaa] at (1,1) {\aaa}; % Why?
\end{tikzpicture}
\typeout{Using coordinates and rotating}
\begin{tikzpicture}[
color=black, rotate=-45
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\pgfmathanglebetweenpoints{\pgfpointanchor{a}{center}}{\pgfpointanchor{b}{center}}\xdef\aaa{\pgfmathresult}};
\node [draw, rotate=\aaa] at (1,1) {\aaa}; % Why?
\end{tikzpicture}
\end{document}


which results in:

and in the log I have the (expected):

Using internal functions
0.0pt,0.0pt--- 2,2
Using coordinates
0.0pt,0.0pt--- 2,2
Using coordinates and scaling
0.0pt,0.0pt--- 2,2
Using coordinates and rotating
0.0pt,0.0pt--- 2,2



So, the first one (green) is not working (I tried adding parenthesis like (\tikztostart) bur still...).

The trick in the blue one is working ok, I can get the angle correctly and draw it.

But then it fails if I scale in an asymmetric way (or with a negative scale factor) and with global rotation. I understand why the calculated angle could be still 45 degrees (we are in the rotated/scaled coordinate system), but then it seems that the rotate of the node is in absolute coordinates.

I do not want to use transform shape, because the result then is the (expected, correct):

It is possible to calculate the path angle so that it works for the red and black case without using the transform shape option?

I thought I found a way, but I am not sure I am doing the right thing here, so I post it for comments. Look (I removed the first thing per @AndréC comment):

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

\makeatletter
\newdimen{\@@xa}
\newdimen{\@@ya}
\newdimen{\@@xb}
\newdimen{\@@yb}
\def\computerot{%
\pgfgettransformentries\a\b\c\d\temp\temp
\pgfextractx{\@@xa}{\pgfpointanchor{a}{center}}
\pgfextracty{\@@ya}{\pgfpointanchor{a}{center}}
\pgfextractx{\@@xb}{\pgfpointanchor{b}{center}}
\pgfextracty{\@@yb}{\pgfpointanchor{b}{center}}
\typeout{XA:\space\the\@@xa\space YA:\space\the\@@ya\space XB:\space\the\@@xb\space YB:\space\the\@@yb}
\typeout{MATRIX\space A:\a\space B:\b\space C:\c\space D:\d}
\pgfmathsetmacro{\newx}{\a*(\@@xb-\@@xa)+\b*(\@@yb-\@@ya)}
\pgfmathsetmacro{\newy}{\c*(\@@xb-\@@xa)+\d*(\@@yb-\@@ya)}
\typeout{NEWX:\space\newx\space NEWY:\space\newy}
\pgfmathsetmacro{\rot}{atan2(\c*(\@@xb-\@@xa)+\d*(\@@yb-\@@ya), \a*(\@@xb-\@@xa)+\b*(\@@yb-\@@ya) )}
\typeout{ROT\space\rot}
}
\makeatother
\begin{document}

\typeout{Using coordinates}
\begin{tikzpicture}[
color=blue]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\computerot
\xdef\aaa{\rot}
};
\node [draw, rotate=\aaa] at (1,1) {\aaa}; % Ok, now it's 45
\end{tikzpicture}
\typeout{Using coordinates and scaling}
\begin{tikzpicture}[
color=red, xscale=2,
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\computerot
\xdef\aaa{\rot}
};
\node [draw, rotate=\aaa] at (1,1) {\aaa}; % Why?
\end{tikzpicture}
\typeout{Using coordinates and rotating}
\begin{tikzpicture}[
color=black, rotate=30,
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b) \pgfextra{%
\typeout{\tikztostart --- \tikztotarget}
\computerot
\xdef\aaa{\rot}
};
\node [draw, rotate=\aaa] at (1,1) {\aaa}; % Why?
\end{tikzpicture}
\end{document}


and this seems to work for the case with different scaling (where the angle, 26 degrees more or less, is correct) but not for rotations: I have 15 degrees when I should have 75 or something around that...

The output is:

Using coordinates
0.0pt,0.0pt--- 2,2
XA: 0.0pt YA: 0.0pt XB: 56.90549pt YB: 56.90549pt
MATRIX A:1.0 B:0.0 C:0.0 D:1.0
NEWX: 56.90549 NEWY: 56.90549
ROT 45.0
Using coordinates and scaling
0.0pt,0.0pt--- 2,2
XA: 0.0pt YA: 0.0pt XB: 56.90549pt YB: 56.90549pt
MATRIX A:2.0 B:0.0 C:0.0 D:1.0
NEWX: 113.81097 NEWY: 56.90549
ROT 26.56505
Using coordinates and rotating
0.0pt,0.0pt--- 2,2
XA: 0.0pt YA: 0.0pt XB: 56.9057pt YB: 56.90572pt
MATRIX A:0.86603 B:0.5 C:-0.5 D:0.86603
NEWX: 77.73476 NEWY: 20.82907
ROT 15.00056


and it seems that for rotation the X and Y coordinates are somewhat swapped.

• the 3.1.4 manual say at 95.5 Angle Computations, i quote "Unlike the rest of the math engine, which is a “standalone” package, the following commands only work in conjunction with the core of pgf." \tikztostart and \tikztotarget are not commands from the pgf core. Jul 29, 2019 at 10:51
• @AndréC, yes, this explains why the first case (green) fails. Jul 29, 2019 at 11:42
• Note that to and -- are not the same. For example \draw (0,0) -- (2,2) node[midway, sloped] {angle}; works and \draw (0,0) to (2,2) node[midway, sloped] {angle}; does not. Jul 29, 2019 at 13:46
• @JohnKormylo yes, but to fix the problem with the linked issue, I must try to make it work for to elements... Jul 29, 2019 at 14:03

\documentclass[]{article}
\usepackage{tikz}
\tikzset{good bye/.code=\pgftransformreset}
\begin{document}
\typeout{Using coordinates and scaling}
\begin{tikzpicture}[
color=red, xscale=2,
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b);
\path[good bye] (a) -- (b) node[midway,sloped,draw] {pft};
\end{tikzpicture}
\typeout{Using coordinates and rotating}
\begin{tikzpicture}[
color=black, rotate=-45
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b);
\path[good bye] (a) -- (b) node[midway,sloped,draw] {pft};
\end{tikzpicture}
\end{document}


To make you happier. I stress that this is unnecessarily complicated, i.e. for all purposes I could imagine there are simpler solutions.

\documentclass[]{article}
\usepackage{tikz}
\makeatletter
\newdimen{\@@xa}
\newdimen{\@@ya}
\newdimen{\@@xb}
\newdimen{\@@yb}
\def\computerot{%
\pgfgettransformentries\a\b\c\d\temp\temp
\pgfextractx{\@@xa}{\pgfpointanchor{a}{center}}
\pgfextracty{\@@ya}{\pgfpointanchor{a}{center}}
\pgfextractx{\@@xb}{\pgfpointanchor{b}{center}}
\pgfextracty{\@@yb}{\pgfpointanchor{b}{center}}
\typeout{XA:\space\the\@@xa\space YA:\space\the\@@ya\space XB:\space\the\@@xb\space YB:\space\the\@@yb}
\typeout{MATRIX\space A:\a\space B:\b\space C:\c\space D:\d}
\pgfmathsetmacro{\newx}{\a*(\@@xb-\@@xa)+\b*(\@@yb-\@@ya)}
\pgfmathsetmacro{\newy}{\c*(\@@xb-\@@xa)+\d*(\@@yb-\@@ya)}
\typeout{NEWX:\space\newx\space NEWY:\space\newy}
\pgfmathsetmacro{\rot}{atan2(\c*(\@@xb-\@@xa)+\d*(\@@yb-\@@ya), \a*(\@@xb-\@@xa)+\b*(\@@yb-\@@ya) )}
\typeout{ROT\space\rot}
}
\makeatother
\tikzset{good bye/.code=\pgftransformreset\computerot%
\xdef\aaa{\rot}%
}
\begin{document}
\typeout{Using coordinates and scaling}
\begin{tikzpicture}[
color=red, xscale=2,
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b)
[good bye] (a) -- (b) node[midway,rotate=\aaa,draw] {pft};
\end{tikzpicture}
\typeout{Using coordinates and rotating}
\begin{tikzpicture}[
color=black, rotate=-45
]
\draw[thin, dotted] (0,0) grid (2,2);
\draw (0,0) coordinate(a) to (2,2) coordinate(b)
[good bye] (a) -- (b) node[midway,rotate=\aaa,draw] {pft};
\end{tikzpicture}
\end{document}

• Yes --- it works for this case, with --, but what I need is the value of the angle --- circuitikz use it for deciding a lot of things about labels etc. Jul 29, 2019 at 19:10
• @Rmano The correct angles are also available. If you add a use case example, I could spell this out.
– user121799
Jul 29, 2019 at 19:13
• If you look at my second example code, I need that the angle in the third (black) example is correct. I can't change the to command, nor the node one --- just find the correct angle in the \pgfextra code. I really can't understand why it's correct in the case of scaling but not in the case of rotation. Could be that one is a coordinate and the other a canvas transormation? Jul 29, 2019 at 19:21
• @Rmano I added something that uses your lower code and seems to work....
– user121799
Jul 29, 2019 at 19:56