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.

I'm trying to connect an edge to a node with the target point being off-center. I would like the edge to end with an arrow at the border of the node without going into the box.

It is easy to connect an edge to a side of a node:

\begin{tikzpicture}
\node (x) [draw,minimum size=1 cm] at (0,0) {x};
\node (y) [draw,minimum size=1 cm] at (2 cm,2 cm) {y};
\draw[->] (x) -- (y.west);
\end{tikzpicture}

But drawing to halfway between (x) and (x.west) continues into the node instead of stopping at the border:

\begin{tikzpicture}
\node (x) [draw,minimum size=1 cm] at (0,0) {x};
\node (y) [draw,minimum size=1 cm] at (2 cm,2 cm) {y};
\draw[->] (x) -- ($ (y.west)!0.5!(y) $);
\end{tikzpicture}

How can I make an edge with the same angle as (x) -- ($ (y.west)!0.5!(y) $) but which draws the arrow right at the border instead of entering into the node?

share|improve this question
    
Somebody temporarily posted an answer using shorten but deleted it. It doesn't quite work for my situation, but it would be nice to leave the answer here because it might be perfect for some closely related situations. –  amcnabb Nov 8 '12 at 23:58
    
As requested I have undeleted it. –  Harish Kumar Nov 9 '12 at 0:33
    
@HarishKumar, thanks! –  amcnabb Nov 9 '12 at 16:07
add comment

2 Answers 2

up vote 7 down vote accepted

With the TikZ library intersections you can find the point on the node's rectangle quite easily.

We give the y node a path name: yborder.
We use one \path command to get the path from (x) to ($ (y.west)!0.5!(y) $) and name it xyline.

With name intersections={of=yborder and xyline} we get coordinates named intersections-1, intersections-2, …
In our case there's only one intersection, so intersection-1 will do.

(The PGF/TikZ manual shows how to deal with path intersections with more than one hit.)

Code

\documentclass[tikz,border=2pt]{standalone}
\usetikzlibrary{calc,intersections}
\begin{document}
\begin{tikzpicture}[every node/.style={draw,minimum size=1 cm}]
    \node                     (x) at (0cm,0cm) {x};
    \node [name path=yborder] (y) at (2cm,2cm) {y};
    \path [name path=xyline ] (x) -- ($ (y.west)!0.5!(y) $);
    \fill [red]               ($(y.west)!0.5!(y)$) circle[radius=1pt]; % Where's my point?
    \draw [name intersections={of=yborder and xyline},->]
                              (x) -- (intersection-1);
\end{tikzpicture}
\begin{tikzpicture}[every node/.style={circle,draw,minimum size=1 cm}]
    \node                     (x) at (0cm,0cm) {x};
    \node [name path=yborder] (y) at (2cm,2cm) {y};
    \path [name path=xyline ] (x) -- ($ (y.west)!0.5!(y) $);
    \fill [red]               ($(y.west)!0.5!(y)$) circle[radius=1pt]; % Where's my point?
    \draw [name intersections={of=yborder and xyline},->]
                              (x) -- (intersection-1);
\end{tikzpicture}
\end{document}

Output

rectanglescircles

share|improve this answer
    
This is a really interesting idea, and I think I might be able to get it to work in my situation. But this won't work for non-rectangle node shapes, will it? –  amcnabb Nov 8 '12 at 23:59
    
@amcnabb I've updated my answer. –  Qrrbrbirlbel Nov 9 '12 at 0:10
    
I was able to use this to get the exact effect I needed. Thanks for the great answer. –  amcnabb Nov 9 '12 at 0:15
    
By the way, the intersection seems to fail if it happens to go right through the southwest corner. This seems like a bug, but I might just have an old version of TikZ. Anyway, this otherwise works perfectly. –  amcnabb Nov 9 '12 at 21:01
    
@amcnabb If I use ($(y.south west)!0.5!(y)$) instead of ($(y.west)!0.5!(y)$), they arrow is pointing to (y.south west). What does “seems to fail”? Is there an error message? I don't get an (intersection-1) point when I use (y) (because in this case TikZ automatically uses the outer border of y, (y.center) does work again). –  Qrrbrbirlbel Nov 9 '12 at 21:09
show 1 more comment

You can use shorten :

\draw[->,shorten >=10pt] (x) -- ($ (y.west)!0.5!(y) $);

Code:

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

\begin{document}
\begin{tikzpicture}
\node (x) [draw,minimum size=1 cm] at (0,0) {x};
\node (y) [draw,minimum size=1 cm] at (2 cm,2 cm) {y};
\draw[->] (x) -- (y.west);
\end{tikzpicture}
\begin{tikzpicture}
\node (x) [draw,minimum size=1 cm] at (0,0) {x};
\node (y) [draw,minimum size=1 cm] at (2 cm,2 cm) {y};
\draw[->,shorten >=10pt] (x) -- ($ (y.west)!0.5!(y) $);
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
How do you programmatically determine how far to shorten by? The edges are created in a \foreach loop, and they won't all be quite the same angles. –  amcnabb Nov 8 '12 at 23:53
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.