[Tex/LaTex] Draw straight line/arrow from between two shapes

tikz-pgf

I am trying to draw a straight arrow from one shape to another, two rectangles precisely. I have an MWE below, but the arrow from rectangle B meets rectangle A at an angle instead of at 90 degrees.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\usepackage{graphicx}

\begin{document}
\begin{tikzpicture}

\tikzstyle{block}=[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};
\draw[->] ([yshift=-2em] B) -- ([yshift=-2em] A);

\end{tikzpicture}

\end{document}

What I am trying to achieve:

enter image description here

Best Answer

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