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.

When drawing a line between two nodes in TikZ, you can specify the anchors on the beginning and end nodes in order to control how the line is drawn.

I would like to specify the anchor on the beginning node, and the angle at which the line is drawn, and let TikZ figure out where it will intercept the end node. The usual use case is when I'm connecting to a "big node" and I would like the lines to be vertical.

I can cheat by placing a coordinate behind the big node, drawing a line to the coordinate instead, and then drawing the big node so that it covers things up. However this won't work if I need to put an arrow on the end.

I could try to calculate the intercept coordinate on the edge of the big node manually, but that seems against the TikZ spirit.

|- doesn't work in this case.

\documentclass[10pt]{minimal}
\usepackage[active,tightpage,pdftex]{preview}
\usepackage{tikz}

\begin{document}
\begin{preview}

\tikzstyle{RectObject}=[rectangle,fill=white,draw,line width=0.5mm]
\tikzstyle{line}=[draw]
\tikzstyle{arrow}=[draw, -latex] 

\begin{tikzpicture}
  %%%%%%%%%%%%%%%%%%%%%%%%
  %%  LEFT SIDE
  %%%%%%%%%%%%%%%%%%%%%%%%
  \draw (1,0) node[RectObject] (Small1A) {A};
  \draw (3,0) node[RectObject] (Small1B) {B};
  \coordinate (Cheat1A) at (1,2);
  \coordinate (Cheat1B) at (3,2);
  \path [line] (Small1A.north) -- (Cheat1A);
  \path [line] (Small1B.north) -- (Cheat1B);

  % need to draw Big Node last to cover up our cheating
  \draw (2,2) node[RectObject, inner xsep=1cm] (Big1) {Big Node};

  \draw (2,4) node[text width=4cm] (text1) {L: Cheating to control line orientation. Arrows would be hard.};

  %%%%%%%%%%%%%%%%%%%%%%%%
  %%  RIGHT SIDE
  %%%%%%%%%%%%%%%%%%%%%%%%
  \draw (7,2) node[RectObject, inner xsep=1cm] (Big2) {Big Node};
  \draw (6,0) node[RectObject] (Small2A) {A};
  \draw (8,0) node[RectObject] (Small2B) {B};
  \path [arrow] (Small2A) -- (Big2);
  \path [arrow] (Small2B) -- (Big2);

  \draw (7,4) node[text width=4cm] (text2) {R: No cheating. Arrows easy. Can't control line orientation.};
\end{tikzpicture}
\end{preview}
\end{document}

Here's a side-by-side example of "cheating", which shows what I want to be able to do, and "not cheating", which does not do what I want.

side-by-side example of "cheating", which shows what I want to be able to do, and "not cheating", which does not do what I want

The left side of this example shows what I want to be able to do, except I want to do it without cheating, and I'd like to put arrows on the end of the lines.

share|improve this question

3 Answers 3

up vote 9 down vote accepted

May be I missunderstood something but I don't see any problem with |- syntax. Using Jake's code:

\documentclass[10pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\tikzstyle{RectObject}=[rectangle,fill=white,draw,line width=0.5mm]
\tikzstyle{line}=[draw]
\tikzstyle{arrow}=[draw, -latex] 

\begin{tikzpicture}
  \draw (7,2) node[RectObject, inner xsep=1cm] (Big2) {Big Node};
  \draw (6,0) node[RectObject] (Small2A) {A};
  \draw (8,0) node[RectObject] (Small2B) {B};
  \draw[arrow] (Small2A.north)--(Small2A|-Big2.south);
  \draw[arrow] (Small2B.north)--(Small2B|-Big2.south);

\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
Oh wow, I never thought of using the syntax inside the node specification! Much more elegant than my approach! –  Jake Jul 13 '11 at 22:25
    
That is slick. I didn't know you could use the |- syntax inside a node specification like that. Originally I said "|- doesn't work" because I was thinking of (Small1A) |- (Big1.south) or something like that. –  andrewtinka Jul 18 '11 at 19:20

Jake and Ignasi's answers are excellent for the example I gave, of wanting strictly vertical lines between nodes. I found a way of doing the same thing with arbitrary orientation of the line. The "intersection of" TikZ mechanism can be used to find the intersection of lines defined by nodes or coordinates. The "intersection" syntax is tricky; it seems that you can't use the "calc" syntax inside an "intersection" specification, so you have to create a new coordinate and do the calculations there.

Example diagram: three nodes, two lines, arbitrary orientation of lines

\documentclass[10pt]{minimal}
\usepackage[active,tightpage,pdftex]{preview}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}

\begin{document}
\begin{preview}

\tikzstyle{RectObject}=[rectangle,fill=white,draw,line width=0.5mm]
\tikzstyle{line}=[draw]
\tikzstyle{arrow}=[draw, -latex] 

\begin{tikzpicture}
  \draw (2,2) node[RectObject, inner xsep=1cm] (Big1) {Big Node};
  \draw (1,0) node[RectObject] (Small1A) {A};
  \draw (3,0) node[RectObject] (Small1B) {B};

  % Method 1: use positioning library to put a coordinate at a special place
  % on the target node.  Doesn't really satisfy my criteria for setting the
  % line's orientation directly.
  \coordinate[left=1.4cm of Big1.south] (Small1AatBig1);
  \path [arrow] (Small1A) -- (Small1AatBig1);

  % Method 2: set a phantom coordinate using polar coordinates, then draw
  % a line to the intersection of the target node and the phantom line
  % Intersection syntax is tricky: no parentheses and no spaces around --
  \coordinate (Phantom) at ($ (Small1B) + (115:5cm) $);
  \path [arrow] (Small1B) -- (intersection of Big1.south--Big1.south east and Small1B--Phantom);

\end{tikzpicture}
\end{preview}
share|improve this answer

Two approaches, both using the TikZ calc library: Either use the syntax ($(A)!(C)!(B)$), which specifies the projection of (C) on the line from (A) to (B), or use the let \p1 = (<coordinate>) in ... syntax, which stores a coordinate in a macro \p1 and lets you access its x and y coordinates separately with \x1 and \y1:

\documentclass[10pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\tikzstyle{RectObject}=[rectangle,fill=white,draw,line width=0.5mm]
\tikzstyle{line}=[draw]
\tikzstyle{arrow}=[draw, -latex] 

\begin{tikzpicture}
  \draw (7,2) node[RectObject, inner xsep=1cm] (Big2) {Big Node};
  \draw (6,0) node[RectObject] (Small2A) {A};
  \draw (8,0) node[RectObject] (Small2B) {B};
  \path [arrow]  let \p1=(Small2A), \p2=(Big2.south) in (Small2A) -- (\x1,\y2);
  \path [arrow] (Small2B) -- ($(Big2.south east)!(Small2B)!(Big2.south)$);

\end{tikzpicture}
\end{document}

vertical lines with arrow tips

share|improve this answer

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.