# Mindmap, automatic/optimization of node placement, need crossfield help for canonic answer

I am certainly lacking of knowledge on graph theory, computing, optimization or probably just geometry ! But just asking the brains here if a solution to the problem in title exists (without external programs?). And if not, what would be the next step(s) to automate harmonious mindmaps ?

Based on multiple questions on mindmaps shape automation (growcyclic circle-shape-for-level-4-or-5, circle-shape-for-level-3, nodes-alongside-a-rectangle ), Schrodinger's cat gave multiple variations on the topic and produced multiple, complex growing functions. With 2 compilations, they are automatically calculating the number of nodes at each level and adapt automatically the sibling angles based on 360/number of nodes on that level.

What works

As mentioned in a previous post, when the Mindmaps are well balanced (with a relatively equal number of nodes and children), the growing function works well and reaches the fantastic objective of focusing on content, and not so much on the organization of the nodes (wasn't it one of the original target of TeX ?).

What worked less...

The problem comes from unbalanced mindmaps with for instance level 2 without level 3 or 4. The nodes look twisted and feel like watchmaking mechanisms where you'd like to shift level 2 by clockwise X% and level 3 counterclockwise by Y% (as below) to make things nicer.

Conclusion so far (by Schrodinger's cat)

"Progress is more if someone provides a concrete idea (a specific algorithm, say) which one can build on. There are many possible modifications of the above one can explore. One particular promising one may be to marry the mindmap story to graph drawing algorithms."

I ran the following code (based on shape-for-level-4-or-5 to have an idea of the shape in limit cases and I get a strange behaviour with distance between nodes (and ever weirder without [clockwise from=0], I hardcoded the sibling angles, I cannot adapt the level distance)

\documentclass[tikz,border=9]{standalone}
\usetikzlibrary{mindmap,decorations}
\makeatletter
\newcount\tikzcountchildi
\newcount\tikzcountchildii
\newcount\tikzcountchildiii
\newcount\tikzcountchildiv
\newcount\tikzcountchildv
\newcount\tikzcountchildvi
\tikzset{garlic growth/.style={growth function=\tikz@grow@garlic,
/tikz/mmap/name=#1,mmap/#1/.is family,
mmap/initialize counts,
execute at end scope={%
\tikz@mmap@store@aux{n-i}{\the\tikzcountchildi}%
\tikz@mmap@store@aux{n-ii}{\the\tikzcountchildii}%
\tikz@mmap@store@aux{n-iii}{\the\tikzcountchildiii}%
\tikz@mmap@store@aux{n-iv}{\the\tikzcountchildiv}%
\tikz@mmap@store@aux{n-v}{\the\tikzcountchildv}%
\tikz@mmap@store@aux{n-vi}{\the\tikzcountchildvi}}},
mmap/.cd,initialize counts/.code={\tikzcountchildi=0%
\tikzcountchildii=0%
\tikzcountchildiii=0%
\tikzcountchildiv=0%
\tikzcountchildv=0%
\tikzcountchildvi=0%
}
}
\def\tikz@mmap@store@aux#1#2{%
\immediate\write\@mainaux{\string\expandafter\xdef\noexpand\csname pgfk@/tikz/mmap/\pgfkeysvalueof{/tikz/mmap/name}/#1\string\endcsname{#2}}}%
\def\tikz@mmap@get@from@aux#1#2{%
\ifcsname pgfk@/tikz/mmap/\pgfkeysvalueof{/tikz/mmap/name}/#1\endcsname
\edef#2{\csname pgfk@/tikz/mmap/\pgfkeysvalueof{/tikz/mmap/name}/#1\endcsname}%
\else
\edef#2{0}%
\fi
}

\newcount\tikzcountgrandchild
\def\tikz@grow@garlic{%
\pgfmathsetmacro{\pgfutil@tempa}{\pgfkeysvalueof{/tikz/mmap/overall rotation}}%
\ifcase\tikztreelevel
\or
\tikz@mmap@get@from@aux{n-i}{\myni}%
\tikz@mmap@get@from@aux{n-ii}{\mynii}%
\tikz@mmap@get@from@aux{n-1-\the\tikzcountchildi}{\mynall}%
\tikz@mmap@get@from@aux{p-1-\the\tikzcountchildi}{\mypi}%
\ifnum\mynii>0
\pgfmathsetmacro{\pgfutil@tempa}{\pgfutil@tempa+\pgfkeysvalueof{/tikz/mmap/sign}%
*(\pgfkeysvalueof{/tikz/mmap/child weight}*(\mypi)*360/\mynii+%
(1-\pgfkeysvalueof{/tikz/mmap/child weight})*(\tikzcountchildi-1)*360/\myni)}%
\fi
\or
\tikz@mmap@get@from@aux{n-ii}{\mynii}%
\tikz@mmap@get@from@aux{n-1-1}{\mynall}%
\ifnum\mynii>0
\pgfmathsetmacro{\pgfutil@tempa}{\pgfutil@tempa+\pgfkeysvalueof{/tikz/mmap/sign}%
*(\tikzcountchildii-1-\mynall/2)*360/\mynii}%
\fi
\ifnum\tikznumberofcurrentchild=1\relax
\tikz@mmap@store@aux{n-1-\the\tikzcountchildi}{\the\tikznumberofchildren}%
\tikz@mmap@store@aux{p-1-\the\tikzcountchildi}{\the\numexpr\tikzcountchildii-1}%
\tikz@mmap@store@aux{a-1-\the\tikzcountchildi-\the\tikzcountchildii}{\pgfutil@tempa}%
\fi
\or
\ifnum\tikznumberofcurrentchild=1\relax
\tikz@mmap@store@aux{n-1-\the\tikzcountchildi-\the\tikzcountchildii}{\the\tikznumberofchildren}%
\tikz@mmap@store@aux{p-1-\the\tikzcountchildi-\the\tikzcountchildii}{\the\numexpr\tikzcountchildiii-1}%
\fi
\tikz@mmap@get@from@aux{n-iii}{\myniii}%
\tikz@mmap@get@from@aux{a-1-1-1}{\bettera}%
\tikz@mmap@get@from@aux{n-1-1-1}{\mynall}%
\ifdim\bettera pt=0pt\relax
\else
\pgfmathsetmacro{\pgfutil@tempa}{\bettera}%
\fi
\ifnum\myniii>0
\pgfmathsetmacro{\pgfutil@tempa}{\pgfutil@tempa+\pgfkeysvalueof{/tikz/mmap/sign}%
*(\tikzcountchildiii-1-\mynall/2)*360/\myniii}%
\fi
\or
\tikz@mmap@get@from@aux{n-iv}{\myniv}%
\ifnum\myniv>0
\pgfmathsetmacro{\pgfutil@tempa}{\pgfutil@tempa+\pgfkeysvalueof{/tikz/mmap/sign}*(\tikzcountchildiv-1)*360/\myniv}%
\fi
\or
\tikz@mmap@get@from@aux{n-v}{\mynv}%
\pgfmathsetmacro{\pgfutil@tempa}{\pgfutil@tempa+\pgfkeysvalueof{/tikz/mmap/sign}*(\tikzcountchildv-1)*360/\mynv}%
\ifnum\mynv>0
\fi
\or
\tikz@mmap@get@from@aux{n-vi}{\mynvi}%
\ifnum\myvi>0
\pgfmathsetmacro{\pgfutil@tempa}{\pgfutil@tempa+(\tikzcountchildvi-1)*360/\mynvi}%
\fi
\fi
\pgftransformreset%
\pgftransformshift{\pgfpoint{\pgfkeysvalueof{/tikz/mmap/overall xshift}}%
{\pgfkeysvalueof{/tikz/mmap/overall yshift}}}%
\pgftransformrotate{\pgfutil@tempa}%
\pgftransformxshift{\the\tikzleveldistance}%
}
\makeatother
\begin{document}
\tikzset{mmap/.cd,
name/.initial=undef,
overall rotation/.initial=00,
overall xshift/.initial=0pt,
overall yshift/.initial=0pt,
sign/.initial=1,
child weight/.initial=0,
/tikz/.cd,
Xshift/.style={xshift=#1,mmap/overall xshift=#1},
Yshift/.style={yshift=#1,mmap/overall yshift=#1},
branch color/.style={
concept color=#1!80,ball color=#1!50,
every child/.append style={concept color=#1!50},
}
}

\begin{tikzpicture}
\begin{scope}[
mindmap,garlic growth=A,
mmap/child weight=0,
mmap/overall rotation=00,
mmap/sign=-1,
root concept/.append style={ball color=blue!50, line width=1.5ex,text=red!80!black,font=\Large\bfseries\scshape,minimum size=2.5cm,text width=2.5cm,},
nodes={concept,align=center, text width=2cm,inner sep=1mm,minimum size=1.0cm,execute at begin node=\hskip0pt},
concept color=blue!50!black,
level 1/.style={nodes=concept,
every child/.append style={concept color=blue!90},
level distance=4cm,
},
level 2/.style={%opacity=0,
%           nodes=concept,
every child/.append style={concept color=blue!70},
level distance=8cm,
%           minimum size=1.0cm
},
level 3/.style={%opacity=0,
%           nodes=concept,
every child/.append style={concept color=blue!50},
level distance=12cm,
%               minimum size=1.0cm,
},
level 4/.style={%opacity=0,
%           nodes=concept,
every child/.append style={concept color=blue!30},
level distance=14cm,
%               minimum size=1.0cm,text width=1.0cm
}
level 5/.style={%opacity=0,
nodes=concept,
%                every child/.append style={concept color=white},
level distance=16cm,
%                minimum size=1.0cm,text width=1.0cm
}
]
\node [root concept]{}
child  foreach \A in {1,2,3,4}{
node[] {\A}
child foreach \B in {1,2,3}{
node[] { \A-\B}
child foreach \C in {1,2,3}{
node { \A-\B-\C}
child[clockwise from=0,sibling angle=10] foreach \D in {1,2}{
node {\A-\B-\C-\D}
child[clockwise from=0,sibling angle=10]  foreach \E in {1,2}{
node {\footnotesize \A-\B-\C-\D-\E}
}
}
}
}
};
\end{scope}
\end{tikzpicture}

\end{document}

• I guess you may want to make a concrete proposal for how the nodes are to be arranged.
– user194703
Apr 21, 2020 at 23:27
• I am trying not to say anything stupid here :) Would it make sense to you if I'd say... The mindmap could be cut as a pie and each color would be a slice?
– JeT
Apr 21, 2020 at 23:36
• I did not want to imply you are saying something negative. ;-) What I mean is that there are two things. One is a prescription and one is to code this. There are many different prescriptions one could try to implement. So there are basically two questions one may ask: (i) propose a new prescription and ask for a LaTeX realization or (ii) specify the way the mindmap should look like (symmetries, relative location of node and their children, etc.) and ask for a prescription and code that realize those. Otherwise it is hard to give a concrete answer.
– user194703
Apr 21, 2020 at 23:41
• Perfectly clear! I'm gonna work on a graphical example to post and edit to include the two questions that should be addressed. Merci the Cat :)
– JeT
Apr 21, 2020 at 23:44
• Your question made something very clear in my mind, I'd like to diminish/minimize the "torsions" between the levels. Trying to word that in a question and graph.
– JeT
Apr 22, 2020 at 0:03