5

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

normal xy-axis

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:

transformation

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.

2
  • 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
    Commented Mar 24, 2018 at 23:33
  • 1
    This is a transformation of the function why do you need nonlinear transformations? Just draw your transformed function on the regular axis
    – percusse
    Commented Mar 24, 2018 at 23:53

1 Answer 1

4

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))

This leads to the code:

\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)}
\pgfmathsetmacro{\myRadius}{veclen(\oriX,\oriY)}
\typeout{original\space x=\oriX\space y=\oriY}
\typeout{radius=\myRadius\space angle=\myAngle}
\setlength{\pgf@x}{\myAngle pt}
\setlength{\pgf@y}{\myRadius pt}
} 
\def\fastertransformation{% modified version of the manual 103.4.2 Installing Nonlinear Transformation
\pgfmathsetmacro{\myAngle}{mod(720+atan2(\pgf@y,\pgf@x),360)}
\pgfmathsetmacro{\myRadius}{veclen(\pgf@x,\pgf@y)}
\setlength{\pgf@x}{\myAngle pt}
\setlength{\pgf@y}{\myRadius 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}

enter image description here

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.

5
  • 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
    Commented Mar 25, 2018 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
    Commented Mar 25, 2018 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
    Commented Mar 25, 2018 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
    Commented Mar 25, 2018 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
    Commented Mar 25, 2018 at 1:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .