Draw straight line/arrow from between two shapes

This looks like a bug for me.

In a strange way if we use ([transform] A) when A is a node, the anchor to, or from, A is calculated before the transformation, and the node A is transformed only afterwards.

In your example :

  1. the anchor to A is calculated, and not to ([yshift=-2em] A), from the shifted B (or more precisely from ([yshift=-2em] B.center));
  2. the anchor from B is calculated, not from ([yshift=-2em] B), to the calculated anchor of A.

Here is an illustration of this.

\documentclass[tikz,border=10]{standalone}
\tikzset{
  block/.style = {draw, minimum width=1.7cm, minimum height=1.2cm, node distance=3cm},
  down/.style={yshift=-7em}
}

\begin{document}
  \begin{tikzpicture}
    % "almost" the original code
    \node[block] (A) at (0,0) {A};
    \node[block,right of=A] (B) {B};
    \draw[->] ([down] B) -- ([down] A)  -- ([down] B);

    % illustration of the anchor calculation
    \begin{scope}[red]
      \node[block] (A2) at ([down] A) {A2};
      \node[block] (B2) at ([down] B) {B2};
      \draw[->] (B2) -- (A);
    \end{scope}

    % and more examples
    \begin{scope}[blue]
      \draw[->] ([down] B) -- ([down] A.east);
      \draw[->] ([down] B.west) -- ([down] A);
    \end{scope}
  \end{tikzpicture}
\end{document}

enter image description here

In conclusion : We can't transform nodes like this, only "real" coordinates are transformed.

Workaround: You can use transform canvas to do your shifts like this :

    \begin{scope}[ transform canvas={yshift=-2em}]
      \draw[->] (B) -- (A);
    \end{scope}

In your particular MWE a workaround will be also to specify the anchors like this :

\draw[->] ([yshift=-2em] B.west) -- ([yshift=-2em] A.east); 

UPDATE: Actually ([transformed] A) looks to have a "double nature" : as a coordinate it is the same as ([transformed] A.center) and as a node it is the same as (A). Here is one example that shows this "double behavior" of coordinate transformed nodes.

\documentclass[tikz,border=10]{standalone}
\tikzset{
  block/.style = {draw,minimum width=1.7cm, minimum height=1.2cm, node distance=3cm}
}

\begin{document}
  \begin{tikzpicture}
    \node[block, circle] (A) at (0,0) {A};
    \node[block,right of=A] (B) {B};

    % ([yshift=-2em] A) behaves like the node (A)
    \foreach \i in {0,30,...,360}
        \draw[blue, ->] (\i:2) -- ([yshift=-2em] A);

    % ([rotate=\i]B) behaves like the point ([rotate=\i]B.center) to calculate the anchor of (A)
    % and then behaves like the node (B) when we draw from it.
    \foreach \i in {0,30,...,360}
      \draw[red,->] ([rotate=\i]B) -- (A);
  \end{tikzpicture}
\end{document}

enter image description here


I don't understand why this is necessary, but a workaround might be:

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{positioning}
\begin{document}

  \begin{tikzpicture}
    [block/.style={
      draw,
      shape=rectangle,
      minimum width=3.5em,
      text width=1.7cm,
      align=center,
      minimum height=1.2cm,
      node distance=3cm}
    ]

    \node[block] (A) at (0,0) {A};
    \node[block, right=of A] (B) {B};% new syntax is recommended using the positioning library
    \draw[->] (B) -- (A);% for comparison only
    \draw[->] (B.west) +(0,-1em) coordinate (b1) -- (A.east |- b1);
  \end{tikzpicture}

\end{document}

lowered arrow

Tags:

Tikz Pgf