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 would like to be able to calculate two new \coordinates by starting from two existing coordinates. I have defined two coordinates c1 and c2. A minimal example would be

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

\begin{document}
    \begin{tikzpicture}[x={(.05\textwidth,0)},y={(0,.05\textwidth)}]
    \def\arrowlength{0.5}
    \coordinate (c1) at (1,0);
    \coordinate (c2) at (4,1);

    \draw (c1) -- (c2);
    \end{tikzpicture}
\end{document}

Continuing from here, I would like to calculate a third coordinate, c3, that lies in the middle of c1 and c2. I have tried

\coordinate (c3) at (0.5*c1+0.5*c2);

but that gives me the error

Package pgf Error: No shape named 0 is known

Second, I would like to draw an arrow from c3, orthogonal to the line between c1 and c2. So I would like to take the difference c2-c1, rotate that vector by 90 degrees, normalize it, multiply it with the length the arrow is supposed to have, then add it to c3 and store it as a new coordinate called c4. Is this possible? (I want to avoid calculating the coordinates manually since I have to do this a lot of times and I want to be able to make changes to it easily)

Edit 1: Thanks to Jake and percusse, I reallized that I have to enclose the expression in $-signs and enclose the coordinates in parentheses. I have now updated the minimal example to

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

\begin{document}
    \begin{tikzpicture}[x={(.05\textwidth,0)},y={(0,.05\textwidth)}]
    \def\arrowlength{0.5}
    \coordinate (c1) at (1,0);
    \coordinate (c2) at (4,1);
    \coordinate (c3) at (5,0);

    \coordinate (c4) at ($(c1)!0.5!(c2)$);
    \coordinate (c5) at ($(c4)!\arrowlength!90:(c2)$);

    \coordinate (c6) at ($(c2)!0.5!(c3)$);
    \coordinate (c7) at ($(c6)!\arrowlength!90:(c3)$);

    \draw (c1) -- (c2) -- (c3);
    \draw[->] (c4) -- (c5);
    \draw[->] (c6) -- (c7);
    \end{tikzpicture}
\end{document}

which produces the image

Arrows are not equally long

As can be seen, the arrows are not equally long, so replacing 2cm (which Jake used) with 0.5 (which I assumed would automatically, like all other coordinates specified without a unit, use the x and y vectors) did apparently not work. Any ideas for how to specify the length of the arrow in terms of "unit lengths"? (The coordinate (4,1) for example is 4 unit lengths in the x-direction and 1 unit length in the y-direction)

Edit 2:

I updated my example according to Jakes suggestion to

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

\begin{document}
    \def\unitlength{0.05\textwidth}
    \begin{tikzpicture}[x={(\unitlength,0)},y={(0,\unitlength)}]
    \def\arrowlength{0.5*\unitlength}
    \coordinate (c1) at (1,0);
    \coordinate (c2) at (4,1);
    \coordinate (c3) at (5,0);

    \coordinate (c4) at ($(c1)!0.5!(c2)$);
    \coordinate (c5) at ($(c4)!\arrowlength!90:(c2)$);

    \coordinate (c6) at ($(c2)!0.5!(c3)$);
    \coordinate (c7) at ($(c6)!\arrowlength!90:(c3)$);

    \draw (c1) -- (c2) -- (c3);
    \draw[->] (c4) -- (c5);
    \draw[->] (c6) -- (c7);
    \end{tikzpicture}
\end{document}

and now the arrows are equally long.

share|improve this question
4  
For questions like this, you should always post a minimal example document. –  Jake Aug 13 '12 at 9:31
2  
Can you also consider accepting the answers in your previous questions as your accept rate(64% now) is an indicator for some users? –  percusse Aug 13 '12 at 9:46
    
@Jake: Got it – I will try to remember that in the future. –  StrawberryFieldsForever Aug 13 '12 at 10:59
    
@percusse: Done. What does accept rate mean by the way? –  StrawberryFieldsForever Aug 15 '12 at 3:49
    
Under your nickname, it shows what percent of the questions you have asked has an accepted solution. –  percusse Aug 15 '12 at 10:02
show 1 more comment

2 Answers

up vote 14 down vote accepted

You can use the calc library for this. See section 13.5 Coordinate Calculations of the manual.

To get the halfway point between two coordinates, you can use the syntax ($(A)!0.5!(B)$) or ($0.5*(A)+0.5*(B)$). For the rotated vector, you can use ($(A)!<length>!<angle>:(B)$).

The midpoint between two coordinates can also be found using a \path command, as Altermundus points out in a comment.

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


\begin{document}
\begin{tikzpicture}
\coordinate (C1) at (0,0);
\coordinate (C2) at (3,2);

%% Use one of the next two lines for calculating the midpoint between two coordinates using the calc library...
\coordinate (C3) at ($(C1)!0.5!(C2)$);
%\coordinate (C3) at ($0.5*(C1)+0.5*(C2)$);

%% Or create coordinates C1, C2 and C3 in one go using a path command (thanks, Altermundus!)
%\path (0,0) coordinate (C1) -- coordinate (C3) (3,2) coordinate (C2);

\coordinate (C4) at ($(C3)!2cm!90:(C2)$);

\draw (C3) -- (C2);
\draw [red] (C3) -- (C4);

\node at (C1) {C1};
\node at (C2) {C2};
\node at (C3) {C3};
\node at (C4) {C4};
\end{tikzpicture}


\end{document}  

share|improve this answer
    
Nice! But I'm running into problems when I'm trying to replace the 2cm with a dimensionless quantity. I've updated my question to include that. –  StrawberryFieldsForever Aug 13 '12 at 12:15
1  
I can't think of a simple way to do this, since you can specify different lengths for x and y. What (physical) length would you expect the dimensionless length 1 to have? I would recommend defining a macro \def\unitlength{0.05\textwidth} before your tikzpicture, and using that macro both in the definition of x and y and in the coordinate calculations. In your example, you could use \def\unitlength{0.05\textwidth} \begin{tikzpicture}[x=\unitlength,y=\unitlength] \def\arrowlength{0.5*\unitlength} –  Jake Aug 13 '12 at 12:21
    
That would definitely be a solution. I recal I have even used a similar method for another problem I ran in to. –  StrawberryFieldsForever Aug 13 '12 at 12:23
1  
Possible to get C3 : \path (0,0) coordinate (C1) -- coordinate (C3) (3,2) coordinate (C2); –  Alain Matthes Aug 13 '12 at 12:33
2  
Assuming the coordinate system is not skewed, the macro \pgf@xx holds the unit x vector. So {\arrowlength*\pgf@xx} would give 0.5 times the unit x vector. But requires \makeatletter somewhere before that –  percusse Aug 13 '12 at 12:46
show 2 more comments

In addition to Jake's answer, when one wants to do a little more complicated point weighting etc. the local shift and scale options are useful (both with x and y counterparts). They map to lower level PGF commands \pgfpointadd and \pgfpointscale commands.

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\draw[style=help lines] (-1,-1) grid[step=1] (1,1);
\node (c1) at (1,1) {c1};
\node (c2) at (-1,-1) {c2};
\node (c3) at (-1,1) {c3};
\coordinate (c4) at ($([shift={(-1,-1)}]c1)+(c2)+([xscale=-1]c3)$);
\draw[-latex] (c4) -- (1,-1);
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
    
Nice! Although for ([shift={(-1,-1)}]c1), I'd prefer the equivalent expression (c1)+(-1,-1), just because it uses less brackets. –  Jake Aug 13 '12 at 10:14
    
@Jake Sure. But if you want to add and scale at the same time, it would cause some trouble. The order of the keys still matter. –  percusse Aug 13 '12 at 11:09
    
Nice. I didn't know that you could scale and shift coordinates that easily. I guess these are also options that you can give to \draw? –  StrawberryFieldsForever Aug 13 '12 at 12:20
1  
@StrawberryFieldsForever Yes, this also works : \draw[shift={(2,2)},scale=2,rotate=90] (0,0) -- (1,1); –  percusse Aug 13 '12 at 12:30
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.