Horizontal - Vertical connectors in a tree (in place of slanted lines)
Another option is to use forest
. In this case, you can dispense with the phantom
node and just use tier
to align P7
with the P4
, P5
etc. I've also updated your code to use the current syntax for arrows, provided by the arrows.meta
library as this is now recommended. I like forest
because specifying a tree involves much less typing!
Updated Solution (Forest version 2+)
\documentclass[tikz, border=5pt]{standalone}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta}
\begin{document}
\tikzset{
treenode/.style = {align=center, inner sep=2pt, rounded corners = 2pt, minimum width = 2cm, text centered, font=\sffamily},
block/.style = {treenode, rectangle, white, font=\sffamily\bfseries, draw=black, fill=black},
}
% Forest version 2.1
\begin{forest}
for tree={
block,
edge+={thick, -{Stealth[]}}
},
forked edges
[P1
[P2
[P3
[P4, tier=terminal]
[P5]
]
]
[P6, calign with current
[P7, tier=terminal]
]
[P8
[P9
[P10]
]
]
]
;
\end{forest}
\end{document}
Original Solution (Forest version 1)
\documentclass[tikz, border=5pt]{standalone}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
\begin{document}
\tikzset{
treenode/.style = {align=center, inner sep=2pt, rounded corners = 2pt, minimum width = 2cm, text centered, font=\sffamily},
block/.style = {treenode, rectangle, white, font=\sffamily\bfseries, draw=black, fill=black},
}
\begin{forest}
for tree={
parent anchor=south,
child anchor=north,
block,
edge path={
\noexpand\path [-{Stealth[]}, \forestoption{edge}, thick]
(!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
},
}
[P1
[P2
[P3
[P4, tier=terminal]
[P5]
]
]
[P6, calign with current
[P7, tier=terminal]
]
[P8
[P9
[P10]
]
]
]
;
\end{forest}
\end{document}
Result
The output is the same, basically, regardless of which solution you use.
When you say horizontal/vertical, do you mean this?
Here is the code:
\documentclass[tikz,border=10]{standalone}
\usetikzlibrary{shapes,arrows}
\begin{document}
\tikzset{
treenode/.style = {align=center, inner sep=2pt, rounded corners = 2pt, minimum width = 2cm, text centered, font=\sffamily},
block/.style = {treenode, rectangle, white, font=\sffamily\bfseries, draw=black, fill=black},
phantom/.style = {},
edge from parent/.style={draw,red,thick},
edge from parent path={(\tikzparentnode.south)-- ++(0,-3mm) -| (\tikzchildnode.north)}
}
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 3in/#1, level distance = 1.5cm}]
\node [block] {P1}
child {node [block] {P2}
child {node [block] {P3}
child {node [block] {P4}}
child {node [block] {P5}}
}
}
child {node [block] {P6}
child {node [phantom] {}
child {node [block] {P7}}
}
}
child {node [block] {P8}
child {node [block] {P9}
child {node [block] {P10}}
}
}
;
\end{tikzpicture}
\end{document}
EDIT: I just discovered that we can use [edge from parent fork down]
style from trees
library to produce the same effect.
A PSTricks solution:
\documentclass{article}
\usepackage{pstricks}
\usepackage{xfp}
\psset{
linecolor = red,
arrows = ->
}
\def\Label(#1,#2)#3{%
\psframe[
framearc = 0.3,
linecolor = black,
fillstyle = solid,
fillcolor = black
](\fpeval{#1-0.5*\widthBox},\fpeval{#2-0.5*\heightBox})%
(\fpeval{#1+0.5*\widthBox},\fpeval{#2+0.5*\heightBox})
\rput(#1,#2){\textcolor{white}{#3}}}
\begin{document}
% parameters
\def\widthBox{1.4}
\def\heightBox{0.4}
\def\horiDist{4.5}
\def\vertDist{1.6}
% drawing
\begin{pspicture}(\fpeval{2*\horiDist+1.75*\widthBox},\fpeval{4*\heightBox+3*\vertDist})
% left
\Label(\fpeval{1.25*\widthBox},\fpeval{2.5*\heightBox+2*\vertDist}){P2}
\psline(\fpeval{1.25*\widthBox},\fpeval{2*\heightBox+2*\vertDist})%
(\fpeval{1.25*\widthBox},\fpeval{2*\heightBox+\vertDist})
\Label(\fpeval{1.25*\widthBox},\fpeval{1.5*\heightBox+\vertDist}){P3}
\psline(\fpeval{1.25*\widthBox},\fpeval{\heightBox+\vertDist})%
(\fpeval{1.25*\widthBox},\fpeval{\heightBox+0.5*\vertDist})%
(\fpeval{0.5*\widthBox},\fpeval{\heightBox+0.5*\vertDist})%
(\fpeval{0.5*\widthBox},\heightBox)
\psline(\fpeval{1.25*\widthBox},\fpeval{\heightBox+0.5*\vertDist})%
(\fpeval{2*\widthBox},\fpeval{\heightBox+0.5*\vertDist})%
(\fpeval{2*\widthBox},\heightBox)
\Label(\fpeval{0.5*\widthBox},\fpeval{0.5*\heightBox}){P4}
\Label(\fpeval{2*\widthBox},\fpeval{0.5*\heightBox}){P5}
% middle
\Label(\fpeval{\horiDist+1.25*\widthBox},\fpeval{3.5*\heightBox+3*\vertDist}){P1}
\psline(\fpeval{\horiDist+1.25*\widthBox},\fpeval{3*\heightBox+3*\vertDist})%
(\fpeval{\horiDist+1.25*\widthBox},\fpeval{3*\heightBox+2*\vertDist})
\Label(\fpeval{\horiDist+1.25*\widthBox},\fpeval{2.5*\heightBox+2*\vertDist}){P6}
\psline(\fpeval{\horiDist+1.25*\widthBox},\fpeval{2*\heightBox+2*\vertDist})%
(\fpeval{\horiDist+1.25*\widthBox},\heightBox)
\Label(\fpeval{\horiDist+1.25*\widthBox},\fpeval{0.5*\heightBox}){P7}
\psline(\fpeval{\horiDist+1.25*\widthBox},\fpeval{1.5*\heightBox+\vertDist-0.1})%
(\fpeval{\horiDist+1.25*\widthBox},\heightBox)
% right
\Label(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{2.5*\heightBox+2*\vertDist}){P8}
\psline(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{2*\heightBox+2*\vertDist})%
(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{2*\heightBox+\vertDist})
\Label(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{1.5*\heightBox+\vertDist}){P9}
\psline(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{\heightBox+\vertDist})%
(\fpeval{2*\horiDist+1.25*\widthBox},\heightBox)
\Label(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{0.5*\heightBox}){P10}
% connection
\psline(\fpeval{\horiDist+1.25*\widthBox},\fpeval{3*\heightBox+2.5*\vertDist})%
(\fpeval{1.25*\widthBox},\fpeval{3*\heightBox+2.5*\vertDist})%
(\fpeval{1.25*\widthBox},\fpeval{3*\heightBox+2*\vertDist})
\psline(\fpeval{\horiDist+1.25*\widthBox},\fpeval{3*\heightBox+2.5*\vertDist})%
(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{3*\heightBox+2.5*\vertDist})%
(\fpeval{2*\horiDist+1.25*\widthBox},\fpeval{3*\heightBox+2*\vertDist})
\end{pspicture}
\end{document}
With this code, all you have to do is choose the width (\widthBox
) and the height (\heightBox
) of the boxes, and the horizontal (\horiDist
) and the vertical (\vertDist
) distances between them. The drawing will then automatically be adjusted accordingly.