6

I like the mindmap library to make mindmaps in tikz. The issue is that the node positioning is manual (and I am extremely lazy), hence the general question:

'is it possible to build a mindmap with automatic node positioning?'

I did my research and I found out that tikz comes along with automatic graph-building algorithms. In particular, it seems that the spring algorithms are the most suitable for building mindmaps, however, I am having two problems:

  1. The setting sibling pre sep to set the minimum distance between the edges of nodes on the same level does not seem to work with the spring algorithms. The result is that some nodes overlap:

Some of the nodes overlap even though sibling pre sep = 1cm

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usetikzlibrary{mindmap,trees, graphs, graphdrawing}
\usegdlibrary{force}
\usepackage{chemformula}
\begin{document}

\begin{figure}
    \centering
    \begin{tikzpicture}[
            spring layout,
            node distance= 6cm,
            sibling pre sep = 1cm, %% some sibling nodes overlap anyway
            font = \small,
            every node/.style = {circle, draw, align =center, text width = 1.5cm},
        ]
        \node{Portland cement paste}
        child { node {Solids in  the cement paste}
                child{node {C-S-H}} 
                child{node{\ch{Ca(OH)2}}}
                child{node {$ \mathrm{C_6A\bar{S}_3H_{32}} $ and $ \mathrm{C_6A\bar{S}H_{18}} $}}
                child{node{Unhydrated p. cement grains}}
            }
        child { node {Voids in the cement paste}
                child{ node {Interlayer space in C-S-H}}
                child{ node {Capillary voids}}
                child{ node{Air voids}}
            }
        child { node {Water in the cement paste}
                child{ node {Capillary water}}
                child{ node {Physically absorbed water}}
                child{ node {Interlayer water}}
                child{ node {Chemically combined water}}
            };
    \end{tikzpicture}
\end{figure}

\end{document}
  1. The mindmap styles do not seem to work (the lines between the nodes are black instead of grey and they do not have the right shape): enter image description here
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usetikzlibrary{mindmap,trees, graphs, graphdrawing}
\usegdlibrary{force}
\usepackage{chemformula}
\begin{document}

\begin{figure}
    \centering
    \begin{tikzpicture}[
            mindmap,
            spring layout,
            node distance= 6cm,
            sibling pre sep = 1cm, %% some sibling nodes overlap anyway
            font = \small,
            every node/.style = {concept, execute at begin node=\hskip0pt},
            concept color=gray!20,
        ]
        \node{Portland cement paste}
        child { node {Solids in  the cement paste}
                child{node {C-S-H}} 
                child{node{\ch{Ca(OH)2}}}
                child{node {$ \mathrm{C_6A\bar{S}_3H_{32}} $ and $ \mathrm{C_6A\bar{S}H_{18}} $}}
                child{node{Unhydrated p. cement grains}}
            }
        child { node {Voids in the cement paste}
                child{ node {Interlayer space in C-S-H}}
                child{ node {Capillary voids}}
                child{ node{Air voids}}
            }
        child { node {Water in the cement paste}
                child{ node {Capillary water}}
                child{ node {Physically absorbed water}}
                child{ node {Interlayer water}}
                child{ node {Chemically combined water}}
            };
    \end{tikzpicture}
\end{figure}

\end{document}

Concluding, If you know the solution to these two issues (node overlapping and mindmap style not working) or you know a better way to draw mindmaps (with automatic node positioning) altogether please let me know. Thank you!

2
  • take a look at this and this
    – JeT
    Jan 12, 2023 at 14:21
  • Thanks for the comment, those are pretty interesting posts. But it is still not what I wanted. (It is most likely that what i want is not implemented in tikz anyway) Jan 18, 2023 at 17:55

2 Answers 2

3

The graphdrawing algorithms provide various possibilities for doing this. Here, a spring electrical layout is used. The alignment commands applicable to other graphdrawing algorithms don't work here so to vertically align one of the child nodes (I chose Solids in the cement paste) with the central node (Portland cement paste), those nodes have to be fixed on the canvas with nail at. Generally, electric charge (here=10) manipulates the distance between the Portland cement paste node and its child nodes. The separation between the leaves of the graph, avoiding the OP's overlap issues, can be manipulated with electric force order. Node and edge styling can be set in the tikzpicture options in the usual manner providing a lot of flexibility.

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

\usetikzlibrary{graphs, graphdrawing, shapes.geometric}
\usegdlibrary{force}
\usepackage{chemformula}

\usepackage{helvet}
\usepackage[T1]{fontenc}
\renewcommand*\familydefault{\sfdefault}

\begin{document}

\begin{tikzpicture}
\graph[
        random seed=10,
        spring electrical layout,
        node distance=3cm,
        cooling factor=0.9,
        electric charge=10, % separation of the parent nodes
        electric force order=1.5, % separation of the child nodes
        coarsen=4,
        iterations=100,
        edges={>=Stealth,line width=2.5pt, color=gray},
        nodes={draw, circle, very thick,font=\sffamily\large,text=black,
        minimum size=3cm, inner sep=1pt, align=center, text depth=0.25ex}
    ]
    {
    "Solids in\\the cement\\paste"[nail at={(0,0)}] <- {"C-S-H",
                                       "\ch{Ca(OH)2}",
                                       "$ \mathsf{C_6A\bar{S}_3H_{32}} $\\and\\$ \mathsf{C_6A\bar{S}H_{18}} $",
                                       "Unhydrated\\p. cement\\grains"
                                     };
                                
    "Voids in\\the cement\\paste" <- {"Interlayer\\space\\in C-S-H",
                                      "Capillary\\voids",
                                      "Air voids"
                                     };

    "Water in\\the cement\\paste" <- {"Capillary\\water",
                                      "Physically\\absorbed\\water",
                                      "Interlayer\\water",
                                      "Chemically\\combined\\water"
                                    };
                                    
    "Portland\\cement\\paste"[nail at={(0,-6)}] <- {"Solids in\\the cement\\paste",
                                  "Water in\\the cement\\paste",
                                  "Voids in\\the cement\\paste"
                                 };
};
\end{tikzpicture}

\end{document}

enter image description here

3
  • 1
    Thank you for your answer! You wrote quite an impressive code where most nodes are positioned automatically. However, I can see it is still necessary to choose where to break (quite annoying) each node's content and set many different parameters right. It seems you would not save much time using this drawing algorithm compared to the manual mindmap library. Again, it seems to me that a completely automatic graph drawing algorithm for mindmaps is missing inTikZ. Returning to your answer, I would say you answered to my points 1 and 3 so i guess i will accept it, thank you. Apr 12, 2023 at 19:04
  • 1
    The benefit of using an algorithm comes when you don't know the layout and you have to discover an efficient representation of the relationships between the vertices. Here the problem is trivial and the first choice solution would be just to draw it.
    – Ross
    Apr 13, 2023 at 10:58
  • Fair reasoning, anyway I kind of changed my mind after playing with the code a bit: it is probably still faster than coding all the positions by hand (even for this simple case). So thank you again for writing the code for me. Apr 15, 2023 at 17:12
1

Here I just want to give more details to Ross' answer. The code below has a bit more comments and I made sure the line break inside the nodes is automatic. Also, I noticed that even without the pins the final result is pretty good.

I think the only issue so far is that the mindmap style does not seem to work with the automatic graph algorithms.

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

\usetikzlibrary{graphs, graphdrawing, shapes.geometric}
\usegdlibrary{force}
\usepackage{chemformula}

\usepackage{helvet}
\usepackage[T1]{fontenc}
\renewcommand*\familydefault{\sfdefault}

\begin{document}

\begin{tikzpicture}
    \graph[
    random seed = 10, % random start configuration
    spring electrical layout, % documentation page sec 32, pag474 pdf of PGF TIKZ manual
    node distance = 7cm, % length at which there is no attraction/repulsion
    convergence tolerance = 0.001, % default 0.01. minimum movement of node in a step (while(movement > tol ... end)
    cooling factor=0.95, % default 0.95. 
    electric charge = 3, % default 1. strength of repulsion/attracion
    electric force order = 3, % default 1. reduce (greater than 1)/increase (0 to 1) long distance forces
    coarsen=true, % default true. read documentation
    iterations=1000, % default 500. maximum number of iterations (while i < iterations ... end)
    edges={>=Stealth,line width=2.5pt, color=gray},
    nodes={draw, circle, very thick, font=\sffamily\large,text=black,
            minimum size=2cm, align=center, text width= 3cm, inner sep = 1pt}
    % text width = 3cm for automatic line break inside the nodes
    % minimum size = 2cm for minimum size of nodes
    ]
    {
    "Solids in the cement paste" <- {"C-S-H",
    "\ch{Ca(OH)2}",
    "$ \mathsf{C_6A\bar{S}_3H_{32}} $ and $ \mathsf{C_6A\bar{S}H_{18}} $",
    "Unhydrated p. cement grains"
    };

    "Voids in the cement paste" <- {"Interlayer space in C-S-H",
    "Capillary voids",
    "Air voids"
    };

    "Water in the cement paste" <- {"Capillary water",
    "Physically absorbed water",
    "Interlayer water",
    "Chemically combined water"
    };

    "A" <- {"B",
    "C",
    "S",
    "E"
    };

    "Portland cement paste" <- {"Solids in the cement paste",
    "Water in the cement paste",
    "Voids in the cement paste",
    "A"
    };

    };
\end{tikzpicture}
\end{document}

enter image description here

You must log in to answer this question.

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