# Is there a TikZ equivalent to the PSTricks \ncbar command?

Although I now use TikZ, every so often I find myself looking for very useful PSTricks commands which don't seem to exist in TikZ. The pst-node package has an \ncbar command which allows one to connect two nodes with arms dropping down, typically at a 90 degree angle. Here's an example:

\documentclass{article}
\usepackage{pst-node}
\begin{document}
\rput(0,0){\rnode{A}{\psframebox{A}}}
\rput(2,0){\rnode{B}{\psframebox{B}}}
\ncbar[angle=90]{A}{B}
\end{document}


Is there a TikZ equivalent to this useful command? If not, how easy would it be to create one?

There's no direct equivalent, but you can use the to path mechanism together with the calc library to do something similar. If you set:

\tikzset{
ncbar angle/.initial=90,
ncbar/.style={
to path=(\tikztostart)
-- ($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)
-- ($(\tikztotarget)!($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztostart)$)
-- (\tikztotarget)
},
ncbar/.default=0.5cm,
}


you can draw a rectangular connection between two coordinates using \draw (a) to [ncbar] (b);. The offset of the line can be controlled using the optional parameter: \draw (a) to [ncbar=1cm] (b);. To change the angle of the connecting line, you can use the key ncbar angle:  \draw [blue] (a) to [ncbar=1.5cm, ncbar angle=70] (b);

\documentclass[landscape]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\tikzset{
ncbar angle/.initial=90,
ncbar/.style={
to path=(\tikztostart)
-- ($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)
-- ($(\tikztotarget)!($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztostart)$)
-- (\tikztotarget)
},
ncbar/.default=0.5cm,
}

\begin{document}
\begin{tikzpicture}
\node [draw] (a) {A};
\node at (2,-1) [draw] (b) {B};

\draw  (a) to [ncbar] (b);
\draw [red] (a) to [ncbar=-1cm] (b);
\draw [blue] (a) to [ncbar=1.5cm, ncbar angle=70] (b);
\end{tikzpicture}
\end{document}

• With some fancy code, you could make it ncbar=1cm at 90 to be able to specify the angle as well (for extra points, ncbar=1cm and ncbar should also work). May 9, 2012 at 13:16
• I think @AndrewStacey is referring to a ncbar/.style args={#1 at #2}{....} type of input parsing. Nevertheless, great stuff. May 9, 2012 at 13:26
• @percusse Almost. You'd have to be a bit more sneaky to be able to handle ncbar=1cm and ncbar=1cm at 90. May 9, 2012 at 13:28
• @AndrewStacey: I'm not sure that that syntax would be preferable, though (not just because it's much more work to implement): If you have a separate angle key, you can set it for all ncbars without specifying it explicitly.
– Jake
May 9, 2012 at 13:34
• Excellent! Should the ncbar angle/.initial be outside the ncbar style to make it possible to set it globally? May 9, 2012 at 15:15

## Code

\documentclass{article}
\usepackage{pst-node,tikz}
\usetikzlibrary{paths.ortho}
\begin{document}
\hspace{.125cm}
\rput(0,0){\rnode{A}{\psframebox{A}}}
\rput(2,1){\rnode{B}{\psframebox{B}}}
\ncbar[angle=90]{A}{B}
\ncbar[angle=45]{A}{B}

\par
\begin{tikzpicture}[thick,nodes=draw]
\node (A)          {A};
\node (B) at (2,1) {B};

\draw (A) ud (B);
\draw[rotate=45] (A) rl (B);
\end{tikzpicture}
\end{document}


## Output

An another answer that gives a command equivalent to the PSTricks \ncbar command :

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

\begin{document}

\tikzset{% TikZ equivalent to the PSTricks \ncbar command
label anchor/.initial={west},%
label rotate/.initial={0},%
arm angleA/.initial={0},%
arm lengthA/.initial={1em},%
}
\newcommand{\anchorL}{\pgfkeysvalueof{/tikz/label anchor}}%
\newcommand{\rotateL}{\pgfkeysvalueof{/tikz/label rotate}}%
\newcommand{\angleA}{\pgfkeysvalueof{/tikz/arm angleA}}%
\newcommand{\lengthA}{\pgfkeysvalueof{/tikz/arm lengthA}}%

\tikzstyle{arrow}=[->, >=stealth, thick, shorten <= 3pt, shorten >= 3pt]%

\newcommand{\nbar}[4][]{% \nbar[options]{node A}{node B}{label}
\begin{tikzpicture}[remember picture,overlay,#1]
\coordinate (p1) at ($(#2)+(\angleA:\lengthA)$) ;
\coordinate (p2) at ($(#3)+(\angleA:\lengthA)$) ;
\pgfmathanglebetweenpoints{\pgfpointanchor{p1}{center}}
{\pgfpointanchor{p2}{center}}
\pgfmathnotless{cos(\pgfmathresult-\angleA)}{0}
\ifnum\number\pgfmathresult=1
% Find the projection of the p2 point on the line from #2 to p1
\coordinate (inter) at ($(#2)!(p2)!(p1)$) ;
\draw[arrow] (#2) -- (inter) -- (p2) -- (#3) ;
\path (inter) -- (p2) node[rotate=\rotateL,anchor=\anchorL,midway]{#4} ;
\else
% Find the projection of the p1 point on the line from #3 to p2
\coordinate (inter) at ($(#3)!(p1)!(p2)$) ;
\draw[arrow] (#2) -- (p1) -- (inter) -- (#3) ;
\path (p1) -- (inter) node[sloped,rotate=\rotateL,anchor=\anchorL,midway]{#4} ;
\fi
\end{tikzpicture}}

\newcommand{\node}[3][]{% \node[options]{node's name}{my node}
\tikz[remember picture,baseline = (#2.base)] \node[#1] (#2) {$#3$};}

\renewcommand{\node}[3][]{% \node[options]{node's name}{my node}
\tikz[remember picture,baseline = (#2.base)] \node[#1] (#2) {#3};}

\begin{minipage}{10cm}
\begin{center}
\node[circle,dashed,draw]{A}{Node A}
\hspace*{3cm}
\raisebox{-10mm}{\node[draw]{B}{Node B}}
\end{center}
\end{minipage}

\nbar[red, arm angleA=70, arm lengthA=5mm,
label anchor=south,label rotate=\angleA-90]{A.\angleA}{B.\angleA}{label}
\nbar[green, arm angleA=150, arm lengthA=5mm,
label anchor=0,label rotate=-90]{A.\angleA}{B.\angleA}{label}
\nbar[blue, arm angleA=-90, arm lengthA=5mm,
label anchor=north,label rotate=0]{A.\angleA}{B.\angleA}{label}

\end{document}