# Logarithmic scaling of picture in tikz

I'm looking for something along the lines of

\begin{scope}[scaling=logarithmic]
...
\end{scope}


The reason is, that I'm trying to visualise whether the Minkowski sums of some specific sets in R^2 (with sort of dyadic partitioning) with balls of a certain radius intersect. The problem is that through this dyadic (i.e. exponential) scaling, things rapidly get indecipherable. I've illustrated the general idea of the plot in the following picture (which uses comparatively small scales and is not representative of what I hope to illustrate).

I'd like to scale down everything - arcs and all - logarithmically (without the Minkowski sums I could just do this manually, but transforming the shells correctly seems like a huge pain), but I haven't found anything about logarithmic scaling except for axes.

 After some clarifying comments about what I actually mean by logarithmic scaling; I'd prefer to transform the whole picture (in polar coordinates) as (r,phi)->(log(r+1),phi), or alternatively (in Cartesian coordinates) as (x,y)->(log(|x|+1),log(|y|+1). [/Edit]

Since the transformation is nonlinear, I suspect one might have to go into PGF? I tried looking in this direction as well - also to no avail, unfortunately.

My code for the plot is:

\documentclass{article}
\usepackage{fullpage}
\usepackage[english]{babel}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}[scale=1/4]
\clip (-2.5,-2.5) rectangle (35,18);
\begin{scope}[very thin,<->]
\draw (-2.5,0) -- (35,0);
\draw (0,-2.5) -- (0,18);
\end{scope}
\foreach \j in {1,...,5} \draw[red] (0,0) circle (2^\j);

\foreach \r / \i [evaluate=\r as \ang using 90/\r] in {8/5,16/3} % radius and number of slice
{
\begin{scope}[rotate={(\i-1)*\ang}]
\draw (-\ang:\r/2) arc (-\ang:\ang:\r/2) -- (\ang:2*\r) arc (\ang:-\ang:2*\r) -- cycle;
\foreach \m in {2} % usually more
{% different code if \m>\r/2
\draw ($(-\ang:\r/2)+(-\ang-90:\m)$) arc (-\ang-90:-\ang-180:\m)
arc (-\ang:\ang:\r/2-\m) arc (\ang+180:\ang+90:\m)
-- ($(\ang:2*\r)+(\ang+90:\m)$) arc (\ang+90:\ang:\m)
arc (\ang:-\ang:2*\r+\m) arc (-\ang:-\ang-90:\m) -- cycle;
};
\end{scope}
};
\end{tikzpicture}
\end{document}


Update: After @percusse's answer showing me how it's done in principle, there are still a few issues left. I'm updating this post because it's way too long for a comment.

The most important thing is that the nonlinear transformation messes up the existing coordinate transformations. This was to be feared, but I hope there is a way to execute all available linear transformations (or better, those within a scope) and then the nonlinear one. This is particularly relevant for longer paths, where the transformations are updated along the way (see example below). Also, linear transformation outside of a scope containing the nonlinear transformation should still apply to the result (in an ideal world).

I found a command in the pgfmanual - \pgfpointtransformednonlinear{<point>}, which

Works like \pgfpointtransformed, but also applies the current nonlinear transformation; that is, it first applies the current linear transformation and then the current nonlinear transformations

This seems to do what should be necessary - but it's only for points and there's no mention of a similar command for paths...

Since I figured that nonlinear transformations are conceptually different, I tried extracting the current linear transformations and feeding it to tikz as a nonlinear one, but it didn't really work. I can post the code if someone is interested - it's based on \def\lintransformation#1#2#3#4#5#6{... which is called with the output of \pgfgettransformentries.

To answer percusse's question, how the result should look like approximately, I attach the following two plots. In the example, the inner region is built around radius 2^4, which means that (due to the construction) its radial border should be bounded by 2^3 and 2^5, resp. the red lines corresponding to 3 and 5 in the log plot. Two telltale signs that something is not working is if one of the following is violated: the transformation should keep the symmetry along the ray around which the support is built (in the unrotated case below, this is the x-axis) and cannot introduce new intersections compared to the case where there's no transformation!

Code for the picture:

\documentclass{article}
\usepackage[english]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}

\usepgfmodule{nonlineartransformations}
\makeatletter
\def\logtransformation{%
\pgfmathveclen{\pgf@x}{\pgf@y}%
\pgfmathparse{log2(\pgfmathresult/28.4+1)}% factor accounts for pt2cm conversion
\pgf@xa=\pgfmathresult pt% somehow faster than using cm
\pgfmathatantwo{\pgf@y}{\pgf@x}%
\pgfmathsincos@{\pgfmathresult}%
\pgfmathmultiply{\pgf@xa}{\pgfmathresultx}\pgf@x=\pgfmathresult cm% USED CM AS UNITS TO SCALE UP !!!
\pgfmathmultiply{\pgf@xa}{\pgfmathresulty}\pgf@y=\pgfmathresult cm% USED CM AS UNITS TO SCALE UP !!!
}
\makeatother

\begin{document}
% complicated version - no long paths
\begin{tikzpicture} %[scale=1/2]
% try uncommenting scale - doesn't affect what is transformed by \logtransformation

\clip (-1,-3) rectangle (6,3);
\draw[<->] (-6,0) -- (6,0);
\draw[<->] (0,-6) -- (0,6);

% the reason I do this before the transformation is to see how it corresponds to the
% untransformed values - this is how I found the factor ~28, which I was able to guess
% had to do with a unit conversion, allowing me to find the exact value.
\foreach \j in {3,5} % dyadic scales below and above the given radius
{
\pgfmathparse{log2(2^\j+1)}% instead of radius \j, incorporates +1 of \logtransformation
\draw[red] circle (\pgfmathresult); % strange: no coordinates! If given, takes y-value as radius!
}

\foreach \r / \i [evaluate=\r as \ang using 90/\r] in {2^4/5} % radius and number of slice
{
\begin{scope} %[rotate={(\i-1)*\ang}]
% try uncommenting rotation - works
\pgftransformnonlinear{\logtransformation}
\draw (-\ang:\r/2) arc (-\ang:\ang:\r/2);
\draw (\ang:\r/2) -- (\ang:2*\r);
\draw (\ang:2*\r) arc (\ang:-\ang:2*\r);
\draw (-\ang:2*\r) -- (-\ang:\r/2);
\foreach \m in {2} % also works for \m=\r/2!
{
\draw ($(-\ang:\r/2)+(-\ang- 90:\m)$) arc (-\ang- 90:-\ang-180:     \m);
\draw ($(-\ang:\r/2)+(-\ang+180:\m)$) arc (-\ang    : \ang    :\r/2-\m);
\draw ($( \ang:\r/2)+( \ang+180:\m)$) arc ( \ang+180: \ang+ 90:     \m);
\draw ($( \ang:\r/2)+( \ang+ 90:\m)$) -- ($( \ang:2*\r)+( \ang+90:\m)$);
\draw ($( \ang:2*\r)+( \ang+ 90:\m)$) arc ( \ang+ 90: \ang    :     \m);
\draw ($( \ang:2*\r)+( \ang :\m)$) arc ( \ang    :-\ang    :2*\r+\m);
\draw ($(-\ang:2*\r)+(-\ang :\m)$) arc (-\ang    :-\ang- 90:     \m);
\draw ($(-\ang:2*\r)+(-\ang- 90:\m)$) -- ($(-\ang:\r/2)+(-\ang-90:\m)$);
};
\end{scope}
}
\end{tikzpicture}~~~
\begin{tikzpicture} % how it should be tikz'd, but doesn't work
\clip (-1,-3) rectangle (6,3);
\draw[<->] (-6,0) -- (6,0);
\draw[<->] (0,-6) -- (0,6);

\foreach \j in {3,5} % dyadic scales below and above the given radius
{
\pgfmathparse{log2(2^\j+1)}% instead of radius \j, incorporates +1 of \logtransformation
\draw[red] circle (\pgfmathresult); % strange: no coordinates! If given, takes y-value as radius!
}

\foreach \r / \i [evaluate=\r as \ang using 90/\r] in {2^4/5} % radius and number of slice
{
\begin{scope} %[rotate={(\i-1)*\ang}]
\pgftransformnonlinear{\logtransformation}
\draw (-\ang:\r/2) arc (-\ang:\ang:\r/2) -- (\ang:2*\r) arc (\ang:-\ang:2*\r) -- cycle;
\foreach \m in {2}
{
\draw ($(-\ang:\r/2)+(-\ang-90:\m)$) arc (-\ang-90:-\ang-180:\m)
arc (-\ang:\ang:\r/2-\m) arc (\ang+180:\ang+90:\m)
-- ($(\ang:2*\r)+(\ang+90:\m)$) arc (\ang+90:\ang:\m)
arc (\ang:-\ang:2*\r+\m) arc (-\ang:-\ang-90:\m) -- cycle;
};
\end{scope}
}
\end{tikzpicture}
\end{document}


Update 2: For completeness, here's the plot with the original parameters - using the unsatisfactory but (up to scaling) working version with the short paths. As I mentioned, the scales will ultimately be higher, this is just for demonstration purposes. The red circles represent powers of 2 - due to the +1-adaptation they would not be exactly equally spaced, so I thought of another adaptation, which basically replaces the radius r by 1/4*r^2+1 if r<2. This polynomial is such that it is 1@0, 2@2 and the derivative is 1@2. A drawback that remains (in addition to lack of pathing) is that for \m=\r/2, some internal parameter exceeds the size maximum of tikz - I see the plot but latex crashes.

For the plot, the only changes in the code from the update are:

...
\pgfmathveclen{\pgf@x}{\pgf@y}%
\pgfmathparse{\pgfmathresult/28.4}% factor accounts for pt2cm conversion
\pgfmathparse{\pgfmathresult > 2 ? \pgfmathresult : 1/4*\pgfmathresult^2+1}
\pgfmathparse{log2(\pgfmathresult)}%
\pgf@xa=\pgfmathresult pt%
...
\foreach \j in {1,...,5} % dyadic scales below and above the given radius
{\node[below right] at (\j,0) {$2^\j$}; \draw[red] (0,0) circle (\j);}
...


• What do you mean by log scaling, just (x,y)->(log(x),log(y)) ? – percusse Jul 7 '14 at 18:26
• @percusse: You're right, I should have been more specific. I just deleted a comment confirming your interpretation, because on second thought, I think it would be much better if it were (in polar coordinates) (r,phi)->(log(r),phi), or maybe even (to avoid problems at the origin) (r,phi)->(log(r+1),phi). – Axel Jul 8 '14 at 9:01
• @percusse: Although I'd now prefer something different, your "just (x,y)->(log(x),log(y)" makes it sound easy. ;-) Do you have any ideas I could pursue in this direction? Thanks! – Axel Jul 10 '14 at 7:44
• @percusse: (x,y)->(log(x+1),log(y+1) would be fine as well - if the polar coordinates are too tricky... I would be glad for any hint you consider worth pursuing (maybe using pgfplots, etc.). – Axel Jul 18 '14 at 8:55
• Dang, I completely forgot it. I'l look into it. One thing though you don't have log for negative numbers so are you always parametrizing at the positive side? – percusse Jul 18 '14 at 11:03

I put some nonlinear transformation but I have no idea whether the result is meaningful or not. I can try to check for mistakes if you can show the before and after result

One thing to consider is that r -> log(r) is a pretty contractive transformation so I boosted up by converting the units to centimeters. I don't know whether it is wise to do.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\usepgfmodule{nonlineartransformations}
\makeatletter
\def\logtransformation{%
\pgfmathveclen{\pgf@x}{\pgf@y}\pgfmathln{\pgfmathresult}%
\pgf@xa=\pgfmathresult pt%
\pgfmathatantwo{\pgf@y}{\pgf@x}%
\pgfmathsincos@{\pgfmathresult}%
\pgfmathmultiply{\pgf@xa}{\pgfmathresultx}\pgf@x=\pgfmathresult cm% USED CM AS UNITS TO SCALE UP !!!
\pgfmathmultiply{\pgf@xa}{\pgfmathresulty}\pgf@y=\pgfmathresult cm% USED CM AS UNITS TO SCALE UP !!!
}
\makeatother

\begin{document}

\begin{tikzpicture}[scale=3]
\begin{scope}[xshift=1cm]
\pgftransformnonlinear{\logtransformation}
% What happens to vertical line
\draw[ultra thick, blue] (2,-10) -- (2,10);
% What happens to horizontal line
\draw[ultra thick,red] (-1,3) -- (7,3);
% What happens to circle
\draw[ultra thick,yellow] (2,2) circle (3cm);

\foreach \r / \i [evaluate=\r as \ang using 90/\r] in {8/7,16/3} % radius and number of slice
{
\begin{scope}[rotate={(\i-1)*\ang}]
\draw (-\ang:\r/2) arc (-\ang:\ang:\r/2) -- (\ang:2*\r) arc (\ang:-\ang:2*\r) -- cycle;
\foreach \m in {4} % usually more
{% different code if \m>\r/2
\draw ($(-\ang:\r/2)+(-\ang-90:\m)$) arc (-\ang-90:-\ang-180:\m)
arc (-\ang:\ang:\r/2-\m) arc (\ang+180:\ang+90:\m)
-- ($(\ang:2*\r)+(\ang+90:\m)$) arc (\ang+90:\ang:\m)
arc (\ang:-\ang:2*\r+\m) arc (-\ang:-\ang-90:\m) -- cycle;
};
\end{scope}
}
\end{scope}
\end{tikzpicture}
\end{document}


Well basically, this is happening

• – kiss my armpit Jul 18 '14 at 18:23
• @Pleasedon'ttouch Good what? – percusse Jul 18 '14 at 22:32
• ooh a dog! :) – Paulo Cereda Jul 19 '14 at 10:48
• Sorry for the late reply, I was gone over the weekend. The answer looks good, unfortunately I can't test it myself yet (e.g. the +1 in the log(r+1) seems to be missing), since my TeXstudio tells me that it can't find the nonlineartransformations module - hopefully, I'll figure out how to fix this soon. I'm optimistic that the effect will be easier to see for higher scales, i.e. higher powers of 2 in the radius. ;-) Thanks again! – Axel Jul 21 '14 at 8:42
• @Axel My pleasure. It needs TikZ version 3.00. You can check your version via putting \pgfversion somewhere on the document body. +1 thing is not needed since I pushed everything via scope shift which admittedly affects the result of course. – percusse Jul 21 '14 at 9:02