# How to do a non-linear transformation with tikz-pgf?

Consider the following plot of the (-2, -1) -- (3, 9) line segment:

I want to apply a transformation so that the horizontal axis is the polar angle of a point, and the vertical axis is the distance between that point and the origin.

It should look like this:

I've taken a look at this question so I believe this should be possible, but I don't really understand the code inside \def\polartransformation.

Any hint about how to do this or links to documentation about those pgfmath functions and pgftransformnonlinear would be appreciated.

• You are in good company, I also do not understand polar transformations. ;-) But I think that the pgfmanual is not entirely accurate at this point, see the commented out text in the code of this answer. – user121799 Mar 24 '18 at 23:33
• This is a transformation of the function why do you need nonlinear transformations? Just draw your transformed function on the regular axis – percusse Mar 24 '18 at 23:53

First of all, I think that the otherwise great pgfmanual is not entirely correct. The manual section 107.4.2 states

% \pgf@x will contain the radius angle
% \pgf@y will contain the distance
\pgfmathsincos@{\pgf@sys@tonumber\pgf@x}%
% pgfmathresultx is now the cosine of radius angle and
% pgfmathresulty is the sine of radius angle
\pgf@x=\pgfmathresultx\pgf@y%
\pgf@y=\pgfmathresulty\pgf@y%

What the code in the pgfmanual is probably doing is to express the x coordinate in pt, then take the cos and sin of x/pt (i.e. if x=50pt then it will return cos(50)), and to multiply the outcome by the y coordinate, i.e.

(x_new,y_new) = (y_old cos(x_old/pt), y_old sin(x_old/pt))

\documentclass{article}
\usepackage{tikz}
\usepgfmodule{nonlineartransformations}
\tikzset{declare function={mymod(\x)=\x-int(\x);}}
\makeatletter
\def\slowtransformation{% modified version of the manual 103.4.2 Installing Nonlinear Transformation
\typeout{before:\space\the\pgf@x\space\the\pgf@y}%
\edef\oriX{\the\pgf@x}%
\edef\oriY{\the\pgf@y}%
\pgfmathsetmacro{\myAngle}{mod(360+atan2(\oriY,\oriX),360)}
\typeout{original\space x=\oriX\space y=\oriY}
\setlength{\pgf@x}{\myAngle pt}
}
\def\fastertransformation{% modified version of the manual 103.4.2 Installing Nonlinear Transformation
\pgfmathsetmacro{\myAngle}{mod(720+atan2(\pgf@y,\pgf@x),360)}
\setlength{\pgf@x}{\myAngle pt}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw[-latex] (-2.3,-2) -- (3.5,-2) node[below]{$x$};
\draw[-latex] (0,-2.3) -- (0,4.5) node[left]{$y$};
\draw[blue]  (-2, -1) -- (3, 4);
\end{tikzpicture}\\
\begin{tikzpicture}
\draw[-latex] (-0.3,0) -- (7.5,0) node[below]{$\varphi$};
\draw[-latex] (0,-0.3) -- (0,4.5) node[left]{$r$};
\pgftransformnonlinear{\slowtransformation}
\draw[blue]  (-2, -1) -- (3, 4);
\end{tikzpicture}
\begin{tikzpicture}
\draw[-latex] (-0.3,0) -- (7.5,0) node[below]{$\varphi$};
\draw[-latex] (0,-0.3) -- (0,4.5) node[left]{$r$};
\pgftransformnonlinear{\fastertransformation}
\draw[blue]  (-2, -1) -- (3, 4);
\end{tikzpicture}
\end{document}


There are two identical transformations, the first one (\slowtransformation) is more explicit and issues \typeouts to understand what's going on, whereas the second one (\fastertransformation) is a bit faster.

NOTE:

• One has to be careful with options like scale=... and the like. This transformation will take the very coordinates after all scale and so on transformations, and then map them to polar coordinates. Therefore, if one has, say, [yscale=0.5] and draws a circle around the origin, the coordinates are those of an ellipse, and the transformation does then not map them to a horizontal line (which it does without any such additional transformations).

• The current code will produce angles between 0 and 360 degrees, and this is controlled by mod(360+atan2(\oriY,\oriX),360). If you use different conventions, you need to adjust this bit of code accordingly.

UPDATES: Fixed two a stupid mistake in the computation of the angle (atan2(y,x) vs atan2(x,y)) and made the axes labels more appropriate. I also removed all scale directives and added more explanations.

• Wow, this is amazing! Of course if the original drawing goes through the positive x axis or the angle abruptly changes from 2*pi to 0 a line appears in the transformation, but I can work around that. Thank you. – kevinz Mar 25 '18 at 1:01
• Also, if a draw a circle I would expect just an horizontal line, but there are some curves that should not be appearing. – kevinz Mar 25 '18 at 1:04
• @kevinz If you replace mod(720+atan2(\pgf@y,\pgf@x),360) by atan2(\pgf@y,\pgf@x), the angle will jump. In the end, the angle is only defined mod 360 degrees, so you can implement your own conventions. And as for the circle, just to be sure: you're talking about a circle around the origin, right? – user121799 Mar 25 '18 at 1:07
• Yes. I just realized the circle thing is due to a different x/y scale, since yscale is 0.5 it is drawing an ellipse instead of a circle and the curves appear. – kevinz Mar 25 '18 at 1:09
• @kevinz I agree. (I was also thinking at first that there is a bug in the transformation, but I think there is none.) Apart from the scale thing, one has to be careful with units. In this sense my above examples are a bit misleading. With your permission I'd like to change them to something without any scale directives (which means that I will modify the y coordinates of the line). – user121799 Mar 25 '18 at 1:21