# Is there a better way to do intersections and calculations with relative coordinates in TikZ?

I've been doing many TikZ diagrams lately and every so often I encounter a situation where I am forced to use some temporary coordinate in a \path. In the following short example, the problem is drawing the red line:

\documentclass{article}
\usepackage{tikz}
%\usetikzlibrary{calc}
\begin{document}

\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

% Angled line connecting to a straigt line. This is where my problem lies.
\draw[red] (A.140) -- ++(0,1) coordinate(temp) -- (temp -| B.50);

% Some examples of what I think would be useful in this case.
% None of these things seem to be supported in TikZ.
%\draw[red] (A.140) |- (+(0,1) -| B.50);
%\draw[red] (A.140) -- ++(1,0) -- (\currentcoordinate -| B.50);
%\draw[red] (A.140) |- ($(B.50).x, (+(0,1)).y$);
\end{tikzpicture}
\end{document}


So I wonder if there is a better way to draw the red line. By "better" I mean more concise, without repetition, ideally without ($calculations$). Some examples of what I think could be useful are included as comments in the code.

Since "better" is mostly a matter of taste, I have broken my question down to what I think could be useful to solve the problem:

1. Is it possible to use relative coordinates in the intersection syntax (a -| b)?
2. Is there some way (macro or other) to access the current coordinate of the current path?
3. Is it possible to use relative coordinates in the calculation syntax ($(a) + (b)$)?
4. Is there a way to combine x-Part of one coordinate with the y-Part of another, other than the (a -| b) syntax? Can it be used with relative coordinates?
-

Before trying to answer your questions, I'd like to make it clear that this is all based on experiment and in trying to follow what goes on through the code. So it's a guess - hopefully and intelligent one, though.

1. Is it possible to use relative coordinates in the intersection syntax (a -| b)?

Not really. What happens is that TikZ sees the -| and assumes that the syntax is (coordinate -| coordinate). It then passes the coordinates back to the parser, but it does so as (coordinate) (since in the -| syntax there are no brackets around the coordinates).

However, there is nothing stopping you defining a new coordinate system which is effectively a relative coordinate system. One has to be a bit careful with groupings since TikZ parses a coordinate by looking for clues and the order in which it does them is therefore important.

2. Is there some way (macro or other) to access the current coordinate of the current path?

Not to my knowledge but it is very easy to define one.

3. Is it possible to use relative coordinates in the calculation syntax ($(a) + (b)$)?

No, but once you have a \currentcoordinate macro then it's easy to use this to make relative coordinates, and once you have an extra relative coordinate system then this can be used as well.

4. Is there a way to combine x-Part of one coordinate with the y-Part of another, other than the (a -| b) syntax? Can it be used with relative coordinates?

Yes! (At last) This can be done using the let syntax (Section 14.15 of the PGF manual, version 2.10).

Here's an example with lots of the above. It's not stress-tested so there may be things that don't work when put in more advanced situations.

\documentclass{article}
%\url{http://tex.stackexchange.com/q/53734/86}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\newcommand\currentcoordinate{\the\tikz@lastxsaved,\the\tikz@lastysaved}

\tikzdeclarecoordinatesystem{+}{%
\tikz@scan@one@point\pgfutil@firstofone+(#1)%
}

\makeatother

\begin{document}

\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

% Angled line connecting to a straigt line. This is where my problem lies.
\draw[red] (A.140) -- ++(0,1) coordinate(temp) -- (temp -| B.50);
\end{tikzpicture}

% Some examples of what I think would be useful in this case.
% None of these things seem to be supported in TikZ.
\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

\draw[red] (A.140) |- ({{$(\currentcoordinate)+(0,1)$}} -| B.50);
\end{tikzpicture}

\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

\draw[red] (A.140) |- ({+ cs:0,1} -| B.50);
\end{tikzpicture}

\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

\draw[red] (A.140) |- ($(+ cs:0,1) + (2,0)$);
\end{tikzpicture}

\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

\draw[red] (A.140) -- ++(0,1) -- (\currentcoordinate -| B.50);
\end{tikzpicture}

\begin{tikzpicture}
% Some nodes. Precise coordinates are unknown.
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

\draw[red] (A.140) let \p1=(B.50), \p2=+(0,1) in |- (\x1,\y2);
\end{tikzpicture}
\end{document}


Results:

-
Very complete answer, you show all the cases – Alain Matthes Apr 30 '12 at 6:18

For advanced path commands like this, to paths are worth a look. They allow you to specify a path between two coordinates in terms of the (\tikztostart) and (\tikztoend). This gives you great flexibility.

For your example, one could define a to path like

(\tikztostart)
-- ($(\tikztostart)+(0,1)$)
-- ({{$(\tikztostart)+(0,1)$}}-|\tikztotarget)


Note that the braces are a bit tricky, Andrew Stacey did a nice analysis of what's required at Combining |- and !.5! in TikZ.

You can even parametrise the to path expression. Here's an example of how this could be used:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\tikzset{
rect connect/.style={
to path={
(\tikztostart)
-- ($(\tikztostart)+(0,#1)$)
-- (
perpendicular cs:
horizontal line through={($(\tikztostart)+(0,#1)$)},
vertical line through={(\tikztotarget)}
)
}
},
rect connect/.default=1
}

\begin{tikzpicture}
\node[draw] at (1,1) (A) {Node};
\node[draw, right of=A, above right=0.5cm] (B) {Other Node};
\draw (B.50) -- ++(0,1);

\draw[red] (A.140) to [rect connect] (B.50);
\draw[blue] (A.70) to [rect connect=1.3] (B.50);

\end{tikzpicture}
\end{document}

-
Jake, to intermingle -|s and calc stuff you need to be very exact about groupings. See tex.stackexchange.com/a/29781/86 for details. – Loop Space Apr 29 '12 at 17:51
@AndrewStacey: Thanks for the link. I tried various levels of groupings (1, 2, and 3), but none of them worked. Would you mind giving it a shot? Essentially, the stuff between ( perpendicular cs: ... ) should be replaceable by a -| expression. – Jake Apr 29 '12 at 18:02
I get that ({{$(\tikztostart)+(0,#1)$}} -| \tikztotarget) works. – Loop Space Apr 29 '12 at 18:23
@AndrewStacey: Ah yes, you're right! Cheers! – Jake Apr 29 '12 at 18:29