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.
[Edit] 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
%\pgfmathlogtwo{\pgfmathresult}% command not found although it's in the documentation?!
\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);}
...
(x,y)->(log(x),log(y))
?(r,phi)->(log(r),phi)
, or maybe even (to avoid problems at the origin)(r,phi)->(log(r+1),phi)
.(x,y)->(log(x),log(y)
" makes it sound easy. ;-) Do you have any ideas I could pursue in this direction? Thanks!(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 usingpgfplots
, etc.).