2

I am trying to generate an ER diagram with automatic positioning of the nodes. This code has got a nice output, but I have to manage manually the position of the nodes. I have tried to replace "left of = person" but doing this way the nodes become overlapped. How can I tell tikz to automatically position the nodes somewhere near "Person"?

\documentclass[a4paper ,11pt,x11names]{article}
\usepackage{tikz}
\usetikzlibrary{er}

\tikzset{multi attribute/.style={attribute,double distance=1.5pt}} 
\tikzset{derived attribute/.style={attribute ,dashed}} 
\tikzset{total/.style={double distance=1.5pt}}
\tikzset{every entity/.style={draw=orange, fill=orange!20}}
\tikzset{every attribute/.style={draw=MediumPurple1, fill=MediumPurple1!20}} 
\tikzset{every relationship/.style={draw=Chartreuse2, fill=Chartreuse2!20}} 

\newcommand{\key}[1]{\underline{#1}}
\begin{document}
    \begin{tikzpicture}[node distance=7em]
        \node[entity] (person) {Person};
        \node[attribute] (pid) [left of = person] {\key{ID}} edge (person); 
        \node[attribute] (name) [above left of=person] {Name} edge (person); 
    \end{tikzpicture}
\end{document}

Output

enter image description here

  • Autoplacement is a quite nontrivial task that TikZ cannot do. You can find an alternative scheme of placement so that they don't overlap and then connect to Person – percusse Mar 29 '16 at 13:58
2

This would not be entirely automatic in all cases, but the positioning library does a better job than the deprecated left of, above left of syntax. For example:

\documentclass[tikz,multi,border=10pt,svgnames,dvipsnames,x11names]{standalone}
\usetikzlibrary{er,positioning}
\tikzset{%
  multi attribute/.style={attribute,double distance=1.5pt},
  derived attribute/.style={attribute ,dashed},
  total/.style={double distance=1.5pt},
  every entity/.style={draw=orange, fill=orange!20},
  every attribute/.style={draw=MediumPurple1, fill=MediumPurple1!20},
  every relationship/.style={draw=Chartreuse2, fill=Chartreuse2!20},
}
\newcommand{\key}[1]{\underline{#1}}
\begin{document}
\begin{tikzpicture}
  \node[entity] (person) {Person};
  \node[attribute] (pid) [left = of person] {\key{ID}} edge (person);
  \node[attribute] (name) [above left = of person] {Name} edge (person);
\end{tikzpicture}
\end{document}

produces

positioning output

Alternatively, if your diagram takes the form of a tree, forest can automatically layout the tree and position the nodes appropriately. For example:

\documentclass[tikz,multi,border=10pt,svgnames,dvipsnames,x11names]{standalone}
\usepackage{forest}
\usetikzlibrary{er}
\tikzset{%
  multi attribute/.style={attribute,double distance=1.5pt},
  derived attribute/.style={attribute ,dashed},
  total/.style={double distance=1.5pt},
  every entity/.style={draw=orange, fill=orange!20},
  every attribute/.style={draw=MediumPurple1, fill=MediumPurple1!20},
  every relationship/.style={draw=Chartreuse2, fill=Chartreuse2!20},
}
\newcommand{\key}[1]{\underline{#1}}
\begin{document}
\begin{forest}
  for tree={%
    grow'=180
  }
  [Person, name=person, entity
    [\key{ID}, name=pid, attribute, calign with current edge]
    [Name, name=name, attribute]
  ]
\end{forest}
\end{document}

Forest positioning

Another option would be the chains library, for example. For truly automatic positioning, you might look at the Lua-based graph drawing algorithms offered by TikZ.

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.