74

I'm having a bit of a headache right now as I can't draw this basic figure:

A straight line goes through points A and B. Another line is perpendicular to AB and goes through an arbitrary point P.

I fiddled with the |- operator but it only seems to work with horizontal or vertical lines. Is this even possible?

Bonus question: when drawing AB, is it possible to let the line poke out a little? For example, when writing \draw (A) -- (B); the line strictly goes from A to B. I'd rather have a line passing through these points but starting 1cm in front of A and ending 1cm after B (for example).

Thank you for your help :)

lockstep
  • 250,273
  • 4
    For the "bonus" question: You could use shorten >=-1cm,shorten <=-1cm together with a pseudo-arrow tip to extend the lines. – Martin Scharrer May 29 '11 at 13:29
  • 4
    @Martin: The shorten (note spelling mistake in your comment) keys work independently of arrow tips so it's not necessary to specify an arrow tip. Thus \draw[shorten >=-1cm] (0,0) -- (2,0); will work. – Andrew Stacey May 29 '11 at 17:44
  • Thanks @Andrew. I figured this out in the meantime. See my comment below Jakes answer. – Martin Scharrer May 29 '11 at 17:46
  • 2
    @Martin: I know, but some people may not read further and just see the comment here so I thought it worth pointing that out here as well. – Andrew Stacey May 29 '11 at 17:50

4 Answers4

85

You can use the calc library for this, which allows to do coordinate calculations. The expression ($(A)!(P)!(B)$) yields the projection of (P) on the line from (A) to (B), for example.

As Martin Scharrer points out, you can extend the lines by using the shorten > and shorten < commands with negative values. I'm using them here in a style called extended line that takes an optional argument to set the length by which to extend the line.

Here's your example:

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

\begin{document}
\begin{tikzpicture}[dot/.style={circle,inner sep=1pt,fill,label={#1},name=#1},
  extended line/.style={shorten >=-#1,shorten <=-#1},
  extended line/.default=1cm]

\node [dot=A] at (0,0) {};
\node [dot=B] at (3,1) {};
\node [dot=P] at (1.9,-1.6) {};

\draw [extended line=0.5cm] (A) -- (B);
\draw [extended line] ($(A)!(P)!(B)$) -- (P);

\fill [red] ($(A)!(P)!(B)$) circle [radius=2pt];

\end{tikzpicture}
\end{document}

tikz projected point

Caramdir
  • 89,023
  • 26
  • 255
  • 291
Jake
  • 232,450
  • 5
    Good answer. Note that you should also be able to give length instead of factors, e.g. ($(A)!-1cm!(B)$) instead of ($(A)!-0.2!(B)$). Also \draw [shorten >=-1cm,shorten <=-1cm] (A) -- (B); works well for the extension of the line. – Martin Scharrer May 29 '11 at 13:58
  • 2
    Good idea with the shorten commands, that's much more readable! – Jake May 29 '11 at 14:02
  • 2
    The structure of this example would also be clearer if you defined, for example, \node (Q) at ($(A)!(P)!(B)$); and made reference to it. – Ryan Reich May 29 '11 at 14:04
  • 2
    This answer has a good explanation of this sort of usage of the calc library – Seamus May 29 '11 at 14:13
  • Thanks for both the calc advice and the shorten shortcut! – megamoustache May 29 '11 at 15:14
  • 5
    @Ryan: In that case you really should use \coordinate instead of \node to avoid issues with borders and minimal size etc. – Martin Scharrer May 29 '11 at 17:47
  • @Martin: theoretically yes, but since he is actually drawing a red circle at Q, I think it is okay to roll the node definition in with the \fill command at the end of the code he gives. Though that would require some reorganization and entail some care that the lines are not drawn over the dot, so perhaps I shouldn't argue. – Ryan Reich May 29 '11 at 21:16
  • @Ryan: You can use coordinate as part of the path as well. Or you could draw the red dot as circle node of course. – Martin Scharrer May 29 '11 at 21:34
  • @Martin: That's what I meant about \filling the circle. – Ryan Reich May 29 '11 at 22:19
  • Excellent answer! I adapted it to: extend line/.style 2 args={shorten >=-#2,shorten <=-#1}, extend line/.default={1cm}{1cm}, so that I could extend by different lengths left and right. – PatrickT Feb 14 '24 at 08:06
19

Here's how to do it using tkz-euclide; the code is, in fact, a variation of one example given in the tkz-euclide examples collection:

\documentclass{article}
\usepackage{tkz-euclide}

\begin{document}

\begin{tikzpicture}[scale=.5]
  \tkzDefPoint(0,0){A}
  \tkzDefPoint(4,2.5){B}
  \tkzDefPoint(4,5){C}
  \tkzDrawLine[add= 0.5 and 0.8,color=blue](A,B)
  \tkzDrawPoints(A,B,C)\tkzLabelPoints(A,B,C)
  \tkzDefLine[orthogonal=through C](A,B)
  \tkzDrawLine[add = .5 and .2,color=red](C,tkzPointResult)
\end{tikzpicture}

\end{document}

enter image description here

EDIT: since tkz-euclide is on CTAN but it is not included in TeX Live (at least not fot the moment), you'll have to download the files and install them manually.

Gonzalo Medina
  • 505,128
9

1) tkz-euclide is on CTAN but not on TexLive I need to upload the sources of the documentation.

2) The solution with calc it's not effective. The next code is from the pgfmanualand I make a zoom on the intersection (see The Syntax of Projection Modifiers)

\begin{tikzpicture} \draw [help lines] (0,0) grid (3,2);
\coordinate (a) at (0,1); 
\coordinate (b) at (3,2); 
\coordinate (c) at (2.5,0);
\draw (a) -- (b) -- (c) -- cycle;
\draw[red]  (a) -- ($(b)!(a)!(c)$); 
\draw[orange] (b) -- ($(a)!(b)!(c)$); 
\draw[blue] (c) -- ($(a)!(c)!(b)$);
\end{tikzpicture}

enter image description here

On some cases, It's impossible to draw geometric picture without errors. In tkz-euclide, if I want a line from A perpendicular to BC, I define a vector BE perpendicular BC, then a vector AD perpendicular to BC and then I search the intersection of AD and BC

3) For the extend style, another solution is :

\tikzset{%
    add/.style args={#1 and #2}{
        to path={%
 ($(\tikztostart)!-#1!(\tikztotarget)$)--($(\tikztotarget)!-#2!(\tikztostart)$)%
  \tikztonodes}}
} 

example : the idea is to use percentage add = 1 and 0, double the line, with 1 and 1 we get the triple, and you can use negative numbers

\documentclass[a4paper]{scrartcl}
\usepackage{tikz} 
\usetikzlibrary{calc}   

\begin{document}

\begin{tikzpicture}[dot/.style={circle,inner sep=1pt,
                   fill,label={#1},name=#1},]
\tikzset{%
add/.style args={#1 and #2}{to path={%
 ($(\tikztostart)!-#1!(\tikztotarget)$)--($(\tikztotarget)!-#2!(\tikztostart)$)%
\tikztonodes}}
}

\node [dot=A](A) at (0,0) {};
\node [dot=B](B) at (3,1) {};  
\node [dot=C](C) at (3,-1) {};  
\draw[add = 1 and 0] (A) to (B);
\draw[add = .5 and .5] (A) to (C);      
\end{tikzpicture}
\end{document} 

enter image description here

Alain Matthes
  • 95,075
6

Just another simpler solution with PSTricks.

enter image description here

\documentclass[pstricks]{standalone}
\usepackage{pst-eucl}
\begin{document}
\pspicture(8,6)
    \pstGeonode(2,3){A}(6,5){B}(6,2){P}
    \pstProjection[PointName=none]{A}{B}{P}
    \psset{nodesep=-1}
    \pstLineAB{A}{B}
    \pstLineAB{P}{P'}
\endpspicture
\end{document}

Applications

To answer this question (click).

\documentclass[pstricks]{standalone}
\usepackage{pst-eucl}
\usepackage{esvect}
\psset
{
    PointName=none,
    PointSymbol=none,
    linejoin=1,
    shortput=nab,
    arrows=->,
}
\begin{document}
\pspicture(8,6)
    \pstGeonode(1,1){A}(2,5){B}(7,3){C}
    \pcline(A)(B)^{$\vv v$}
    \pcline(A)(C)_{$\vv u$}
    \pstProjection{A}{C}{B}
    \pstRightAngle{C}{B'}{B}
    \pstMarkAngle{B'}{A}{B}{$\theta$}
    \psset{linecolor=blue}%
    \everypsbox{\color{blue}}%
    \pcline(B')(B)_{$\vv{v}_{{\scriptscriptstyle\bot}\vv u}$}
    \pcline(A)(B')_{$\vv{v}_{{\scriptscriptstyle\parallel}\vv u}$}
\endpspicture
\end{document}

enter image description here