5

So here is my code that produces a circle with text inside and three clouds, also with text, around it. I would like the clouds to curve in an arc around the circle, if that is possible. There is this thread here, but I do not know how to adopt the code to my case

\documentclass[tikz, preview=true, border=2mm]{standalone}

\renewcommand*\familydefault{\sfdefault}

\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{mindmap,trees,shadows}
\usetikzlibrary{positioning}
\usetikzlibrary{shapes}
\pgfplotsset{compat=1.7}

\begin{document}
    \makeatletter
    \def\tikz@compute@circle@radii@b{%
        \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{center}}}%
        \pgf@xa=\pgf@x%
        \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztostart}{west}}}%
        \advance\pgf@xa by-\pgf@x%
        \pgf@xa=.6\pgf@xa\relax%
        \pgfkeys{/pgf/decoration/start radius/.expanded=\the\pgf@xa}%
        \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{center}}}%
        \pgf@xa=\pgf@x%
        \pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikztotarget}{west}}}%
        \advance\pgf@xa by-\pgf@x%
        \pgf@xa=.3\pgf@xa\relax%
        \pgfkeys{/pgf/decoration/end radius/.expanded=\the\pgf@xa}%
    }

    \def\tikz@compute@segmentamplitude@b{%
        \pgf@x=\pgfkeysvalueof{/pgf/decoration/start radius}\relax%
        \ifdim\pgf@x>\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
        \pgf@x=\pgfkeysvalueof{/pgf/decoration/end radius}\relax%
        \fi%
        \pgf@x=.4\pgf@x\relax%
        \edef\pgfdecorationsegmentamplitude{\the\pgf@x}%
    }
    \tikzoption{thick bar concept color}{%
        \let\tikz@old@concept@color=\tikz@concept@color%
        \let\tikz@old@compute@circle@radii=\tikz@compute@circle@radii%
        \let\tikz@compute@circle@radii=\tikz@compute@circle@radii@b%
        \let\tikz@old@compute@segmentamplitude=\tikz@compute@segmentamplitude%
        \let\tikz@compute@segmentamplitude=\tikz@compute@segmentamplitude@b%
        \def\tikz@edge@to@parent@path{
            (\tikzparentnode)
            to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
            (\tikzchildnode)}
        \def\tikz@concept@color{#1}%
    }
    \tikzoption{thicker bar concept color}{%
        \let\tikz@old@concept@color=\tikz@concept@color%
        \let\tikz@old@compute@circle@radii=\tikz@compute@circle@radii%
        \let\tikz@compute@circle@radii=\tikz@compute@circle@radii@b%
        \let\tikz@old@compute@segmentamplitude=\tikz@compute@segmentamplitude%
        \let\tikz@compute@segmentamplitude=\tikz@old@compute@segmentamplitude%
        \def\tikz@edge@to@parent@path{
            (\tikzparentnode)
            to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
            (\tikzchildnode)}
        \def\tikz@concept@color{#1}%
    }
    \tikzoption{standard bar concept color}{%
        \let\tikz@old@concept@color=\tikz@concept@color%
        \let\tikz@compute@circle@radii=\tikz@old@compute@circle@radii%
        \let\tikz@compute@segmentamplitude=\tikz@old@compute@segmentamplitude%
        \def\tikz@edge@to@parent@path{
            (\tikzparentnode)
            to[circle connection bar switch color=from (\tikz@old@concept@color) to (#1)]
            (\tikzchildnode)}
        \def\tikz@concept@color{#1}%
    }

    \makeatother

    \begin{tikzpicture}

    \begin{scope}[mindmap,
    every node/.style={concept, circular drop shadow, minimum size=0pt,execute at begin node=\hskip0pt},
    root concept/.append style={
        concept color=black, line width=1.5ex},
    level 1 concept/.append style={},
    text=white,
    partner/.style={thick bar concept color=gray!70!black},
    colleague/.style={thicker bar concept color=gray!70!black},
    staff/.style={standard bar concept color=gray!70!black},
    grow cyclic,
    level 1/.append style={level distance=6.2cm,sibling angle=45},
    level 2/.append style={level distance=3cm,sibling angle=45},
    ]
    \node [root concept,font=\huge] {\color{white}Big text}
    child[partner, grow=30, level distance=45mm] {node[draw=black,double,cloud,fill=black!75, inner sep=-16pt, cloud puffs=14, aspect=2, rotate=-60, text width=4.5cm] {\color{white}Some interesting \textbf{text} with an equation in it $x^2+5x-3=0$}
    }
    child[colleague, grow=-90, level distance=45mm] {node[draw=black,double,cloud,fill=black!75, inner sep=-40pt, cloud puffs=20, aspect=5, text width=8.5cm] {\color{white}Some important details here plus a bit of controversy to spark a discussion for example}
    }
    child[partner, grow=150, level distance=40mm] {node[draw=black,double,cloud,fill=black!75, inner sep=-2pt, cloud puffs=8, aspect=2, rotate=57, text width=2.5cm] {\color{white}Last piece of text that people have to deal with}
    };
    \end{scope}

    \end{tikzpicture}
\end{document}

The result:

enter image description here

  • What do you want to do with this exactly? That looks very much like three clouds, with text, around a circle. So isn't that precisely what you're looking for? How should it look if not like that? – cfr Jan 28 '18 at 22:55
  • Also, maybe look at smartdiagram in case something there is what you're after. (I'm not sure what it is you're after, so I don't know. But it can draw various kinds of these ping-ping-ping-done diagrams.) – cfr Jan 28 '18 at 22:57
  • Just to let you know: I'm still trying to complete my solution. However, there is one point where I am stuck, namely combining this transformations with rotations and translations. In principle, there should be no problems because I am using relative coordinates for all my computations, but in practice there are. So at the moment i do not know if I can overcome these obstacles. – user121799 Feb 5 '18 at 3:36
  • @marmot Thank you for putting in so much effort. What are you referring to with the words "this transformations". I tried looking at your answer and th elink you have provided in it to modify my code. The problem I encountered was that I can't get the non-linear transformations to apply to the children inside the mindmap. – ThunderBiggi Feb 8 '18 at 10:27
  • @ThunderBiggi My problems start before that. If I put the whole stuff in a scope with xshift, yshift or rotate, then there are some mysterious effects. – user121799 Feb 8 '18 at 12:13
4

I am interpreting your question as follows: you want to deform the clouds and the text such that the longer axis of the cloud (interpreted as an ellipse) is on a circle with center in the "big text" node, right? If this is the case, then I believe to have made some progress. However, there are still a few steps missing to a solution, so I'd like to check with you if this is what you want.

Assuming it is, one can use nonlinear transformations. Consider this example:

\documentclass{article}
\usepackage{tikz}
\usepgfmodule{nonlineartransformations}
\usetikzlibrary{shapes}
\usetikzlibrary{patterns}
\newcommand{\mytypeout}[1]{\relax}
\makeatletter
% from https://tex.stackexchange.com/q/56353/121799
\newcommand{\gettikzxy}[3]{%
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
% from the manual section 103.4.2
% \pgf@x will contain the \xout{radius} angle
% \pgf@y will contain the distance \pgfmathsincos@{\pgf@sys@tonumber\pgf@x}%
% pgfmathresultx is now the cosine of \xout{radius} radius and 
% pgfmathresulty is the sine of radius 
% \pgf@x=\pgfmathresultx\pgf@y% 
% \pgf@y=\pgfmathresulty\pgf@y%
% what the thing in the pgf manually is probably doing it 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 multiply the outcome by a the y coordinate
% (x_new,y_new) = (y_old cos(x_old/pt), y_old sin(x_old/pt))
% now comes a slightly modified version
\def\marmotransformation{% modified version of the manual 103.4.2 Installing Nonlinear Transformation
\mytypeout{before:\space\the\pgf@x\space\the\pgf@y\space\xC\space\yC}%
\edef\oriX{\the\pgf@x}%
\edef\oriY{\the\pgf@y}%
\mytypeout{original\space x=\oriX\space y=\oriY}
\advance\pgf@x by -\xC% relative
\advance\pgf@y by -\yC% coorinates
\edef\relX{\the\pgf@x}%
\edef\relY{\the\pgf@y}% Yes, there is a more elegant solution based on \pgfpointadd
\mytypeout{xrel=\relX\space yrel=\relY}%
\pgfmathsetmacro{\relNx}{\xN-\xC}%
\pgfmathsetmacro{\relNy}{\yN-\yC}%
\pgfmathtruncatemacro{\testNx}{\xN-\xC}%
\pgfmathtruncatemacro{\testNy}{\yN-\yC}%
\ifnum\testNx=0\relax
\ifnum\testNy>0\relax
\pgfmathsetmacro{\angleN}{90}%
\else
\pgfmathsetmacro{\angleN}{-90}%
\fi
\else
\pgfmathsetmacro{\angleN}{atan(\relNy/\relNx)}%
\fi
\pgfmathsetmacro{\LeN}{sqrt((\relNx)^2+(\relNy)^2)}%
\mytypeout{relNx=\relNx,\space relNy=\relNy,\space LeN=\LeN,\space angleN=\angleN}%
\pgfmathsetmacro{\myp}{(\relX*\relNx+\relY*\relNy)/(\LeN*28.3465)}
\pgfmathsetmacro{\myo}{(((\relY*\relNx-\relX*\relNy))/(5*28.3465)+\angleN)}
\mytypeout{new\space p=\myp,\space o=\myo}
\pgfpointadd{\pgfqpoint{\xC}{\yC}}{\pgfpointpolarxy{\myo}{\myp}}
\mytypeout{after:\space\the\pgf@x\space\the\pgf@y}%
} % I have no idea why the factor 5 is needed
% I'm using https://tex.stackexchange.com/a/167109/121799
\begin{document}
\noindent
\begin{minipage}{9cm}
In order to set the problem up properly, let's have a look at the picture on the
right. There is a center $C$, which corresponds to center of the ``Big text''
node in your example, and the coordinate $N$, which corresponds to the center of
a given cloud that is to be deformed, i.e.\ the fixed point of the
transformation. We are now looking for a transformation
that maps the blue line to the red line. Consider a point $P$ with coordinates
$(x_P,y_P)$. We can decompose its coordinates into a part $p$ that is parallel to the line
$CN$ and an orthogonal part $o$,
\begin{eqnarray*} % I'm using archaic environments here because I don't want to load more packages than absolutely necessary
 p & = &\frac{\displaystyle(x_P-x_O,y_P-y_O)\cdot
 \left(\begin{array}{c}x_N-x_O\\ y_N-y_O\end{array}\right)}{\sqrt{(x_N-x_O,y_N-y_O)\cdot(x_N-x_O,y_N-y_O)}}
\;,\\
 o & = &
 \frac{\displaystyle(y_P-y_O,x_O-x_P)\cdot
 \left(\begin{array}{c}x_N-x_O\\ y_N-y_O\end{array}\right)}{\sqrt{(x_N-x_O,y_N-y_O)\cdot(x_N-x_O,y_N-y_O)}}
 \;.
\end{eqnarray*}
$P'$ has then the polar coordinates 
\[P'\colon \left(\frac{360}{2\pi}\frac{o}{p}\colon p\right)
\quad\mbox{with}~\frac{360}{2\pi}~=~57.2985
\;.\]
\end{minipage}\hspace*{1cm}%
\begin{minipage}{5cm}
\begin{tikzpicture}
 \node[circle,fill,scale=0.4,draw,label=below:$C$] (C) at (0,0) {};
 \node[circle,fill,scale=0.4,draw,label=above:$N$] (N) at (2,4) {};
 \draw[thick,-,blue] (0,5)-- (4,3);
 \draw[dashed,-] (C) -- (N);
 \draw[-,thick,red] (N) arc[radius={2*sqrt(5)}, start angle=63.4, end angle=93.4];
 \draw[-,thick,red] (N) arc[radius={2*sqrt(5)}, start angle=63.4, end angle=33.4];
 \node[circle,fill,scale=0.4,draw,label=above:\textcolor{blue}{$P$},blue] (P) at (1,4.5) {};
 \node[circle,fill,scale=0.4,draw,label=below:\textcolor{red}{$P'$},red] (Pp) at (78.4:{2*sqrt(5)}) {};
\end{tikzpicture}
\end{minipage}\\
\begin{tikzpicture}
\node at (-6,5) {original};
\node[draw,
    cloud,
    cloud puffs = 10,
    pattern=north east lines,
    minimum width=5cm,
    minimum height=2.75cm,
] at (-6,3){};
\draw[-,blue](-8,3)--(-4,3);
\node[circle,fill,scale=0.4,draw,label=below:$C$] (oriC) at (-6,0) {};
\node[circle,fill,scale=0.4,draw,label=above:$N$] (oriN) at (-6,3) {};
%
\node at (0,5) {transform};
\node[circle,fill,scale=0.4,draw,label=below:$C$] (C) at (0,0) {};
\gettikzxy{(C)}{\xC}{\yC}
\node[circle,fill,scale=0.4,draw,label=above:$N$] (N) at (0,3) {};
\gettikzxy{(N)}{\xN}{\yN}
\begin{scope}[transform shape nonlinear=true]
\pgftransformnonlinear{\marmotransformation} 
\node[draw, cloud,
    cloud puffs = 10,
    pattern=north east lines,
    minimum width=5cm,
    minimum height=2.75cm,
] at (0,3){};
\draw[-,blue](-2,3)--(2,3);
\end{scope}
\end{tikzpicture}
\clearpage

Of course, if one sets the fixed point node $N$ differently, the outcome will change.\\*
\begin{tikzpicture}
\node at (-6,5) {original};
\node[draw,
    cloud,
    cloud puffs = 10,
    pattern=north east lines,
    minimum width=5cm,
    minimum height=2.75cm,
] at (-6,3){};
\draw[-,blue](-8,3)--(-4,3);
\node[circle,fill,scale=0.4,draw,label=below:$C$] (oriC) at (-7,0) {};
\node[circle,fill,scale=0.4,draw,label=above:$N$] (oriN) at (-6,3) {};
%
\node at (0,5) {transform};
\node[circle,fill,scale=0.4,draw,label=below:$C$] (C) at (-1,0) {};
\gettikzxy{(C)}{\xC}{\yC}
\node[circle,fill,scale=0.4,draw,label=above:$N$] (N) at (0,3) {};
\gettikzxy{(N)}{\xN}{\yN}
\begin{scope}[transform shape nonlinear=true]
\pgftransformnonlinear{\marmotransformation} 
\node[draw,
    cloud,
    cloud puffs = 10,
    pattern=north east lines,
    minimum width=5cm,
    minimum height=2.75cm,
] at (0,3){};
\draw[-,blue](-2,3)--(2,3);
\end{scope}
\end{tikzpicture}


An unsolved problem is how to deal with additional tranformations.\\*
\begin{tikzpicture}
\node at (-6,5) {original};
\node[draw,
    cloud,
    cloud puffs = 10,
    pattern=north east lines,
    minimum width=5cm,
    minimum height=2.75cm,
] at (-6,3){};
\draw[-,blue](-8,3)--(-4,3);
\node[circle,fill,scale=0.4,draw,label=below:$C$] (oriC) at (-7,0) {};
\node[circle,fill,scale=0.4,draw,label=above:$N$] (oriN) at (-6,3) {};
%
\node at (0,5) {transform};
\node[circle,fill,scale=0.4,draw,label=below:$C$] (C) at (-1,0) {};
\gettikzxy{(C)}{\xC}{\yC}
\node[circle,fill,scale=0.4,draw,label=above:$N$] (N) at (0,3) {};
\gettikzxy{(N)}{\xN}{\yN}
\begin{scope}[transform shape nonlinear=true,rotate=-120]
\pgftransformnonlinear{\marmotransformation} 
\node[draw,cloud,
    cloud puffs = 10,
    pattern=north east lines,
    minimum width=5cm,
    minimum height=2.75cm,
] at (0,3){};
\draw[-,blue](-2,3)--(2,3);
\end{scope}
\end{tikzpicture}\\*
This is not so much a problem caused by the nonlinearity of the transformation.
Rather I do not know yet how to tell Ti$k$Z in which order the transformations
are to be done. The same thing happens with linear transformations, e.g.\ when
combining rotations and translations.
\end{document}  

enter image description here

It does deform the clouds in a way similar to you want. By adjusting the locations of the origin C and the fixed point N you can modify the outcome. There are currently two weak points, which prevented me from applying this to your example. First, I fail to tell TikZ in which order the transformations are to be executed. Second, the current way of defining C and N is not too elegant.

| improve this answer | |
  • What you described and what I see in the picture is exactly what I need. I am at work at the moment, so I can't have a proper look at the code to see if I would be able to udnerstand it – ThunderBiggi Jan 29 '18 at 9:31
  • @ThunderBiggi The code is not finished yet. I just wanted to make sure that I interpret your question correctly. I hope to complete the code within a few days. The math is clear (I think), I am struggling with TikZ and @ characters and so on. – user121799 Jan 29 '18 at 16:08
  • Yes you do interpret it correctly. The above picture is exactly what we want. Thank you very much for taking the time! – ThunderBiggi Jan 29 '18 at 17:52
  • @ThunderBiggi I'd like to have some input from your side. Should the blue and red lines in the above example have the same lengths, or should the lengths depend on the distance? In the second case, do you have a recommendation how the dependence should look like? – user121799 Jan 30 '18 at 18:43
  • The red lines should be longer. Would it be possible to have a parameter to control their length as a multiple of the length of the blue line (which is based on how much text there will be in the cloud?). – ThunderBiggi Jan 30 '18 at 18:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.