# Compute the x distance between two nodes

Is there a way to define a macro which would evaluate to the x part of the distance between two nodes? I know there are the point registers \p and the correspoding \x commands, but I find them rather cumbersome.

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{positioning}

\newcommand{\xdist}[2]{%
% Should compute a parseable representation of the
% x part of the distance between two nodes
1cm
}

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=0.2cm of a] (b) {b\strut};
\node[rectangle,draw,below=0.2cm of b.south east,
anchor=north east,
minimum width=\xdist{b.east}{a.west}] (ab) {ab\strut};
\end{tikzpicture}
\end{document}


In the above MWE, the \xdist command is supposed to compute the minimum width of the ab node, but the value is currently hard-coded.

I am looking for a better way of Creating a node fitting the horizontal width of two other nodes.

-
– Qrrbrbirlbel Dec 19 '13 at 17:41

new version

The idea from percusse here can be applied in this case and the code is better.

 \documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{positioning}

\makeatletter
\tikzset{minimum dist/.code 2 args={%
\path (#1);
\pgfgetlastxy{\xa}{\ya}
\path (#2);
\pgfgetlastxy{\xb}{\yb}
\pgfpointdiff{\pgfpoint{\xa}{\ya}}%
{\pgfpoint{\xb}{\yb}}%
\pgf@xa=\pgf@x}
,
minimum width=\pgf@xa
}

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=2.2cm of a] (b) {b\strut};
\node[rectangle,draw,below=0.2cm of b.south east,
anchor=north east,minimum dist={a.west}{b.east}] (ab) {ab\strut};
\end{tikzpicture}
\end{document}


A macro is not a function ( mathematical term). When yo use minimum width you need to give a length. I'm not a great (TeX)pert but I think it's difficult to make exactly what you want (call a macro and get only the length).

A possibility

 \documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{positioning}

\makeatletter
\tikzset{minimum dist/.style n args={4}{%
insert path={%
\pgfextra{%
\pgfpointdiff{\pgfpointanchor{#1}{#2}}%
{\pgfpointanchor{#3}{#4}}%
\pgf@xa=\pgf@x}
},
minimum width=\pgf@xa}
}

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=2.2cm of a] (b) {b\strut};
\node[rectangle,draw,below=0.2cm of b.south east,
anchor=north east,minimum dist={a}{west}{b}{east}] (ab) {ab\strut};
\end{tikzpicture}
\end{document}


Update

A variant to use 2 arguments only.

 \documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{positioning}

\makeatletter
\tikzset{minimum dist/.style 2 args={%
insert path={%
\pgfextra{%
\path (#1);
\pgfgetlastxy{\xa}{\ya}
\path (#2);
\pgfgetlastxy{\xb}{\yb}
\pgfpointdiff{\pgfpoint{\xa}{\ya}}%
{\pgfpoint{\xb}{\yb}}%
\pgf@xa=\pgf@x}
},
minimum width=\pgf@xa}
}

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=2.2cm of a] (b) {b\strut};
\node[rectangle,draw,below=0.2cm of b.south east,
anchor=north east,minimum dist={a.west}{b.east}] (ab) {ab\strut};
\end{tikzpicture}
\end{document}


If you need to get the minimum height, the next code gives the two dimensions

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{positioning}

\makeatletter
\newdimen\y@min@dim
\newdimen\x@min@dim
\tikzset{h minimum dist/.code 2 args={%
\path (#1);
\pgfgetlastxy{\xa}{\ya}
\path (#2);
\pgfgetlastxy{\xb}{\yb}
\pgfpointdiff{\pgfpoint{\xa}{\ya}}%
{\pgfpoint{\xb}{\yb}}%
\y@min@dim=\pgf@y}
,
minimum height=\y@min@dim
}
\tikzset{w minimum dist/.code 2 args={%
\path (#1);
\pgfgetlastxy{\xa}{\ya}
\path (#2);
\pgfgetlastxy{\xb}{\yb}
\pgfpointdiff{\pgfpoint{\xa}{\ya}}%
{\pgfpoint{\xb}{\yb}}%
\x@min@dim=\pgf@x}
,
minimum width=\x@min@dim
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=2.2cm of a] (b) {b\strut};
\node[rectangle,draw,below=0.2cm of b.south east,
anchor=north east,
w minimum dist={a.west}{b.east}] (hab) {h ab\strut};
\node[rectangle,draw,right=0.2cm of b.south east,
anchor=south west,
h minimum dist={b.south}{a.north}
] (wab) {w ab\strut};

\node[rectangle,draw=red,
anchor=north west,
h minimum dist={b.south}{a.north},
w minimum dist={a.west}{b.east},
] (test) at (a.north west) {test};
\end{tikzpicture}
\end{document}


-
Very beautiful solution. – Paul Gaborit Jul 19 '12 at 7:43
Thanks but it's not exactly what the OP wants but my english is not good enough to explain the confusion between function and macro and I don't know if we can use a trick to find a workaround. – Alain Matthes Jul 19 '12 at 7:52
@Altermundus: No, the solution is indeed beautiful. Is there a way to reduce it to two parameters so that I can pass a.west and b.east straight away? – krlmlr Jul 19 '12 at 7:55
Yes it's possible. With TeX and the same method, it's possible to find the node name and the anchor from a.west and it's possible with TikZ. I updated my code with a TikZ approach. – Alain Matthes Jul 19 '12 at 8:16
@PolGab not so beautiful, minimum dist/.code 2 args is better – Alain Matthes Jul 24 '12 at 7:08

Edit: Here is a better solution via let operation:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,calc}

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=0.2cm of a] (b) {b\strut};

\path let \p{1}=(a.west), \p{2}=(b.east), \n{x dist}={abs(\x{2}-\x{1})} in
node[rectangle,draw,below=0.2cm of b.south east,anchor=north east,minimum width=\n{x dist}]
(ab) {ab\strut};
\end{tikzpicture}
\end{document}


First answer: Here is your example modified to use \setxveclength:

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{positioning}

\makeatletter
\newcommand\setxveclength[5]{% newmacro, node1, anchor1, node2, anchor2
\pgfpointdiff{\pgfpointanchor{#2}{#3}}{\pgfpointanchor{#4}{#5}}
\edef#1{\the\pgf@x}
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node[rectangle,draw] (a) {a\strut};
\node[rectangle,draw,below right=0.2cm of a] (b) {b\strut};
\setxveclength{\mydist}{a}{west}{b}{east}
\node[rectangle,draw,below=0.2cm of b.south east,
anchor=north east,
minimum width=\mydist] (ab) {ab\strut};
\end{tikzpicture}
\end{document}


-
Nice, but not quite what I was looking for. Is there a way to stick to the interface I am suggesting (two arguments, returning the length rather than setting a length with it)? And if not, why? – krlmlr Jul 18 '12 at 23:40
\pgfpointdiff is enough to get the xand y of a vector. – Alain Matthes Jul 19 '12 at 7:25
@Altermundus Yes! I change my answer to use \pgfpointdiff. – Paul Gaborit Jul 19 '12 at 7:39
A little shortcut is using \edef#1{\the\pgf@x} directly after pgfpointdiff but then we need to have makeatletter ... makeatother so not much of a shortcut :) – percusse Jul 19 '12 at 8:11
@percusse: it's a good shortcut. This avoids the use of two arbitrary macro names (\xa and \ya). So, a new edition... – Paul Gaborit Jul 19 '12 at 8:32