# TikZ: How to accurately calculate the distance between nodes anchors? - Effect of outer separation on anchors location

In this code, I configured the text width=2cm and inner sep=0cm with horizontal node separation of 1cm. Therefore, I should assume that the horizontal distance between start.north and end.north is 2*0.5 + 1 + 2*0.5 = 3cm.

However, in the first example, I entered a horizontal shift of 3cm for the line segment which doesn't 100% accurately align with end.north. You can notice this little deviation from the output of the second example using the simple command -|.

Did I misunderstand or miss something?

Edit

In pgfmanual, under outer sep, there is a statement

This option adds an additional (invisible) separation space of hdimensioni outside the background path. The main effect of this option is that all anchors will move a little “to the outside.”

So, if both anchors start.north and end.north are shifted by the same amount, why would I need to add an additional \pgflinewidth to the horizontal 3cm segment according to the comments?

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning,shapes.geometric,calc}
\begin{document}
\begin{tikzpicture}[>=latex',very thick,align=center]

\tikzset{%
block/.style= {draw, rectangle, text width=2cm,inner sep=0cm,minimum height=1cm,node distance=2cm and 1cm}
}

\node [block]  (start1) {Start1};
\node [block, right = of start1] (end1) {End1};
\node [block, below = of start1] (start2) {Start2};
\node [block, right = of start2] (end2) {End2};

\path[draw,->]
(start1.north) -- ++(0,1cm) -- ++(3cm,0) -- (end1.north);

\path[draw,->]
(start2.north) -- ++(0,1cm) -| (end2.north);
\end{tikzpicture}
\end{document}


• You have to consider also line width. Try ++(3cm+\pgflinewidth,0) – Ignasi Jun 13 '16 at 8:07
• Many thanks, you are right. I would be grateful if you put a complete answer with a brief explanation to be comprehensive and informative for anyone including me. – Diaa Jun 13 '16 at 8:10
• Actually, it is twice the outer xseps (by default set to .5\linewidth). You might also want to do (start.north) --++(up:1cm) -- ([shift=(up:1cm)] end.north) -- (end) if you can't use -| or similar. – Qrrbrbirlbel Jun 13 '16 at 8:32
• @Qrrbrbirlbel Thanks, but could you provide a comprehensive answer below since I am quite new to TikZ and not familiar with the meaning of outer xsep. – Diaa Jun 13 '16 at 8:38
• @Qrrbrbirlbel Interesting. I didn't know you could use up like that. – cfr Jun 13 '16 at 11:14

In this kind of case, it is easier to visualise things if you exaggerate the relevant dimensions. In this case, a large line width (and, hence, a large outer sep) may help:

w1 and w2 are the text widths of the nodes.

Adding your arrow from the top of the first to the top of the second node, the problem should be clear:

That is, the problem Qrrbrbirlbel pointed out is not a regular displacement of each anchor by a standard amount - such a pattern would, as you say, not affect the arrow which uses only relative coordinates. Rather, it is that the default outer sep of each node pushes the anchors further apart because the distance between the nodes is measured from the outer borders of those nodes and not from the centre of the line drawn around them.

Here's the code:

\documentclass[tikz,border=10pt,multi]{standalone}
\usetikzlibrary{arrows.meta,positioning,quotes,backgrounds}
\begin{document}
\newlength\nd
\setlength\nd{30mm}
\begin{tikzpicture}
[
every edge quotes/.style={fill=white, inner sep=1pt, font=\footnotesize, text=red, midway},
grey node/.style={draw=gray!50, line width=5mm, draw opacity=.5, inner sep=0pt, minimum height=20mm, text centered},
red line/.style={ultra thin, draw=red},
red dim/.style={>={Stealth[fill=red]}, <->},
red mini dim/.style={>={Stealth[fill=red, scale=.5]}, <->},
red anchor/.style={draw=red, ultra thin, fill=white},
grey arrows/.style={help lines, -{Stealth[]}},
]
\coordinate (o);
\foreach \j/\k [count=\no, remember=\j as \lastj, remember=\k as \lastk] in {n/40,m/30}
{
\ifnum\no=1
\node (\j) [grey node, text width=\k mm] {Node \no};
\else
\node (\j) [grey node, right=\nd of \lastj, text width=\k mm] {Node \no};
\fi
\path [red line] (\j.north west) rectangle (\j.south east) ([xshift=-.5*\k mm, yshift=10mm]\j.center)  -| ++(\k mm,-5mm) edge [red dim, "$w_\no$"]  ++(-\k mm,0) -- ++(0,-15mm) -| cycle;
\foreach \i in {north, south, east, west, north east, north west, south east, south west} \path [red anchor] (\j.\i) circle (.5mm);
\ifnum\no=1
\relax
\else
\path [red line] ([yshift=-5mm]\lastj.east) edge ["node distance", red dim] ++(\nd,0);
\path [red line] ([yshift=-10mm]\lastj.east) edge [draw=none, every edge quotes/.append style={name=s}, "outer sep", red dim] ++(\nd,0);
\path [draw, -Stealth, shorten <=.5mm, shorten >=.5mm] (\lastj.north) -- ++(0,10mm) -- ++(.5*\lastk mm,0) -- ++(\nd,0) -- ++(.5*\k mm,0) -- (\j.north);
\fi
}
\path [red line, red mini dim] ([yshift=-7.5mm]n.east) -- ++(-2.5mm,0) coordinate [midway] (n1) coordinate (n2);
\path [red line, red mini dim] ([yshift=-7.5mm]m.west) -- ++(2.5mm,0) coordinate [midway] (m1) coordinate (m2);
\draw [grey arrows] (s) -| (m1);
\draw [grey arrows] (s) -| (n1);
\begin{scope}[on background layer]
\coordinate (p) at ([yshift=5mm]current bounding box.north);
\coordinate (g) at ([yshift=-5mm]current bounding box.south);
\foreach \i in {n.center,m.center,m2,n2,n.east,m.west} \draw [blue!50!cyan!75!gray, ultra thin, densely dashed] (\i |- p) -- (\i |- g);
\end{scope}
\end{tikzpicture}
\end{document}

• For the second time in a row, you gave me a solid informative answer with comprehensive explanation. I am highly appreciative of your time and effort you dedicated to this answer. Not all heroes wear capes :) – Diaa Jun 14 '16 at 0:51
• Well it is just what Qrrbrbirlbel said but with pictures, really. – cfr Jun 14 '16 at 1:25
• I know right, but graphic illustration made me figure it out and removed my confusion, and it took you time and effort which I have to appreciate and be grateful for. – Diaa Jun 14 '16 at 1:35