Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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}

Result of compilation

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.

share|improve this question
    
Related: TikZ: Make node height span several others –  Qrrbrbirlbel Dec 19 '13 at 17:41
add comment

2 Answers 2

up vote 12 down vote accepted

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}

enter image description here

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}

enter image description here

share|improve this answer
    
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
show 6 more comments

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}

enter image description here

share|improve this answer
1  
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
1  
\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
1  
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.