3

There is a library in TikZ for creating mind (or concept) maps (https://pgf-tikz.github.io/pgf/pgfmanual.pdf#section.60).

However, it doesn't seem that intuitive to use. I want nodes to automatically adjust to their content (which can partly be achieved with https://tex.stackexchange.com/a/285655/194783).

Additionally, I want the mind map to be arranged (at least semi-)automatically.

So that things like in this MWE don't happen:

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

\begin{document}
\pagestyle{empty}
{\centering
    \makebox[0pt]{
        \begin{tikzpicture}
            [mindmap,
            grow cyclic,
            every node/.style={concept, text width=},
            concept color=teal!40,
            ]
            \node {node}
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                };
        \end{tikzpicture}
    }
    \par
}
\end{document}

result

I assume, in CSS, one defines margins to have non-overlapping elements.

Part of the solution might include setting dynamic sibling angles (like in https://tex.stackexchange.com/a/118746/194783) and defining a custom growth function (as described in https://tex.stackexchange.com/a/232914/194783).

Edit: To mitigate the problem, I added some code to automatically set the sibling angle based on the number of children of a node. This still doesn't always avoid overlap, though.

I have seen several posts about writing custom growth functions to achieve a special shape. This also often solves overlaps, but I don't want the shapes that are used there.

For a related problem, there is the forest package suggested, which doesn't entirely help in my case: Overlapping nodes in a tree using TikZ

2
  • I'm interested in this too, shame there doesn't seem to be much of a solution to this as it would be handy! I'm guessing there is a solution that could be calculated using a kind of force of attraction and repulsion between nodes, but I'm nowhere near savvy enough to do this with LaTeX. Commented Nov 4, 2023 at 13:32
  • 1
    @AshOldershaw take a look @ topanswers.xyz/tex?q=1808
    – JeT
    Commented Apr 15 at 21:08

1 Answer 1

2

All credit to @Marmot on topanswers.xyz/tex?q=1808

enter image description here

\documentclass[tikz,border=3mm]{standalone}

\usetikzlibrary{mindmap,shadows}

% growCycle

\makeatletter
\newif\ifmmap@debug
\mmap@debugfalse
\newcommand{\mmap@debug@message}[1]{\ifmmap@debug
    \typeout{#1}%
    \fi}
\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
}   
\pgfmathdeclarefunction{MMapNodesAtLevel}{1}{%
\tikz@mmap@get@from@aux{n-\@roman{#1}}{\pgfmathresult}}
\newcount\tikzcountchildi
\newcount\tikzcountchildii
\newcount\tikzcountchildiii
\newcount\tikzcountchildiv
\newcount\tikzcountchildv
\newcount\tikzcountchildvi
\tikzcountchildi=0
\tikzcountchildii=0
\tikzcountchildiii=0
\tikzcountchildiv=0
\tikzcountchildv=0
\tikzcountchildvi=0
\tikzset{Julien growth/.style={growth function=\tikz@grow@Julien,
    mmap/initialize counts,
    /tikz/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={\global\tikzcountchildi=0%
        \global\tikzcountchildii=0%
        \global\tikzcountchildiii=0%
        \global\tikzcountchildiv=0%
        \global\tikzcountchildv=0%
        \global\tikzcountchildvi=0%
    }
}


\def\tikz@grow@Julien{%
    \pgftransformreset% 
    \pgftransformshift{\pgfpoint{\pgfkeysvalueof{/tikz/mmap/overall xshift}}%
        {\pgfkeysvalueof{/tikz/mmap/overall yshift}}}%
    \ifcase\tikztreelevel 
    \or
        \pgfmathsetmacro{\pgfutil@tempb}{\pgfkeysvalueof{/tikz/mmap/overall rotation}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/offset angle}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/sibling angle}*\tikzcountchildi}%
        \global\advance\tikzcountchildi by1\relax%
    \or
        \pgfmathsetmacro{\pgfutil@tempb}{\pgfkeysvalueof{/tikz/mmap/overall rotation}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/offset angle}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/sibling angle}*\tikzcountchildii}%
        \global\advance\tikzcountchildii by1\relax%
    \or
        \pgfmathsetmacro{\pgfutil@tempb}{\pgfkeysvalueof{/tikz/mmap/overall rotation}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/offset angle}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/sibling angle}*\tikzcountchildiii}%
        \global\advance\tikzcountchildiii by1\relax%
    \or
        \pgfmathsetmacro{\pgfutil@tempb}{\pgfkeysvalueof{/tikz/mmap/overall rotation}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/offset angle}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/sibling angle}*\tikzcountchildiv}%
        \global\advance\tikzcountchildiv by1\relax%
    \or
        \pgfmathsetmacro{\pgfutil@tempb}{\pgfkeysvalueof{/tikz/mmap/overall rotation}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/offset angle}%
            +\pgfkeysvalueof{/tikz/mmap/sign}*\pgfkeysvalueof{/tikz/sibling angle}*\tikzcountchildv}%
        \global\advance\tikzcountchildv by1\relax%
    \fi
    \mmap@debug@message{level=\the\tikztreelevel,%
        \the\tikzcountchildi,\the\tikzcountchildii,\the\tikzcountchildiii,
        rotation=\pgfutil@tempb,sibling angle=\pgfkeysvalueof{/tikz/sibling angle}}%
    \pgftransformrotate{\pgfutil@tempb}%
    \pgftransformxshift{\the\tikzleveldistance}%
}
\makeatother
                
                
\tikzset{%
mmap/.cd,
    name/.initial=undef,
    overall rotation/.initial=0,
    overall xshift/.initial=0pt,
    overall yshift/.initial=0pt,
    sign/.initial=1,                
    child weight/.initial=0.5,      
/tikz/.cd,
    offset angle/.initial=0, %%% Not exist anymore
    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{document}
    
% you may want to use pgf keys for those (did not change them)
\def\ShapeAngle{360}                % half circle
\def\Rotation{0}            
\def\DistOne{5cm}
\def\DistTwo{8cm}
\def\DistThree{11cm}
\def\OffsetLevelThree{0}


% Part to automate

\begin{tikzpicture}%[node font=\sffamily]                           
    \begin{scope}
        [   text width=1.5cm,
            align=flush center,
            mindmap,Julien growth,
            mmap/overall rotation=\Rotation,mmap/sign=1,
            mmap/name=semicirc,%<- you need unique names if you want to use several mindmaps
            every node/.style={concept,circular drop shadow,execute at begin node=\hskip0pt,text=white},    
            node font=\sffamily,
            nodes={concept},
            concept color=teal!40,
            root concept/.append style={ball color=teal!40, line width=1.5ex,text=white,font=\huge\bfseries\scshape,minimum size=4.5cm,text width=4.5cm,},                   
            level 1/.style={level distance=\DistOne,font=\large,minimum size=2.5cm,text width=2.0cm, 
            sibling angle/.evaluated={\ShapeAngle/max((MMapNodesAtLevel(1)-1),1)}},
            level 2/.style={level distance=\DistTwo,font=\normalsize,minimum size=1.5cm,text width=1.5cm, 
            sibling angle/.evaluated={\ShapeAngle/max((MMapNodesAtLevel(2)-1),1)}},
            level 3/.style={level distance=\DistThree,font=\normalsize,minimum size=1.5cm,text width=1.5cm, 
            sibling angle/.evaluated={\ShapeAngle/max((MMapNodesAtLevel(3)-1),1)},
            offset angle=\OffsetLevelThree},
        ]
        \node[root concept] {node} 
        child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                }
                child{
                    node {subnode}
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                    child { node {subnode} }
                };  
    \end{scope}
\end{tikzpicture}
\end{document}

You must log in to answer this question.

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