44

Given two points (defined, for instance using nodes), I want to compute the distance between them.

  1. Is there some build in functionality in tikz to do this?
  2. If not, how can it be done using the mathematical engine?

The application I have in mind is to draw an circular arc centered at (a) and passing through some second point (b), where only (a) and (b) are known.

3
  • Have a look at the through library for this purpose. Dec 16, 2011 at 11:29
  • 4
    What about veclen(a,b)?
    – Ignasi
    Dec 16, 2011 at 11:46
  • @Ignasi I would use the typical computationsqrt((vx)^2+(vy)^2) instead of veclen(vx,vy) (see my answer below). veclen has a quite low precision. For example for (vx,vy)=(10,10), the real norm value is 14.142135623.... For veclen we get 14.14154 while sqrt((vx)^2+(vy)^2) yields 14.14213. Such an error can make a difference for certain purposes. Jun 29, 2021 at 11:54

3 Answers 3

29

As wh1t3 commented, there is a through library which even has the command circle through. Here is the example in the manual: After adding the line \usetikzlibrary{through} in the preamble,

\begin{tikzpicture}
\draw[help lines] (0,0) grid (3,2);
\node (a) at (2,1.5) {$a$};
\node [draw] at (1,1) [circle through={(a)}] {$c$};
\end{tikzpicture}

You can do this using the calc library with almost the same convenience (on which Ignasi commented while I was typing the answer). You can further use this for other purposes: Modfying the example slightly and using \usetikzlibrary{calc} in the preamble, you can get the vector length by using the veclen command as

\begin{tikzpicture}
\coordinate [label=left:$A$] (A) at (0,0);
\coordinate [label=right:$B$] (B) at (2,2);

\draw[red,line width=1mm] let \p1 = ($(B)-(A)$) in (A) -- ++(45:({veclen(\x1,\y1)}););
\draw (A) -- (B);
\draw[blue] (A) let \p1 = ($(B)-(A)$) in -- ++({veclen(\x1,\y1)},0) arc (0:45:({veclen(\x1,\y1)}););
\end{tikzpicture}

which would give

enter image description here

4
  • The minimal example you provided is almost what I was after. I didn't manage to get rid of the horizontal blue edge. I only want the arc... Thanks in advance!
    – Dror
    Dec 16, 2011 at 12:18
  • 1
    @Dror Just remove -- in the last line ;)
    – percusse
    Dec 16, 2011 at 12:24
  • 1
    Thanks! After correcting some unbalanced parentheses your code was what I was looking for! Thanks!
    – Dror
    Dec 16, 2011 at 19:22
  • @Dror Oops, fixed!
    – percusse
    Dec 17, 2011 at 1:50
29

With TikZ, you have the answer with percusse, with pgfmath is the same method but you need to determine the coordinates vx, vy of the vector formed by the two points and then \pgfmathparse{veclen(vx,vy)} the result is in \pgfmathresult.

Personally, I take a few fantasies with the TikZ's syntax. I do not find very satisfactory the syntax let \p1 \n1 and I prefer to calculate the length before drawing the objects. In addition, in some cases the result is not very fine also I use fp to calculate the length. Lua is also a possibilty. It's also possible to use the library fpu with TikZ.

\documentclass[11pt]{scrartcl}
\usepackage{tikz,fp}
\usetikzlibrary{calc}

\makeatletter
\def\calcLength(#1,#2)#3{%
\pgfpointdiff{\pgfpointanchor{#1}{center}}%
             {\pgfpointanchor{#2}{center}}%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\FPeval\@temp@a{\pgfmath@tonumber{\pgf@xa}}%
\FPeval\@temp@b{\pgfmath@tonumber{\pgf@ya}}%
\FPeval\@temp@sum{(\@temp@a*\@temp@a+\@temp@b*\@temp@b)}%
\FProot{\FPMathLen}{\@temp@sum}{2}%
\FPround\FPMathLen\FPMathLen5\relax
\global\expandafter\edef\csname #3\endcsname{\FPMathLen}
}
\makeatother

\begin{document} 

  5cm = 5*28.45274 pt =142.2637pt

\begin{tikzpicture}
\coordinate (A) at (1,2);
\coordinate (B) at (4,6);
\calcLength(A,B){mylen}
% \draw (A) circle (\mylen pt); % pt is important here
\end{tikzpicture}
With calclength the length of AB is : \mylen

\begin{tikzpicture}
\coordinate (A) at (1,2);
\coordinate (B) at (4,6);
\path (A) let   \p1 = ($ (B) - (A) $),  \n1 = {veclen(\x1,\y1)} 
    in -- (B) node[draw]  {With veclen the length is :\n1};
\end{tikzpicture}   

\end{document}

enter image description here

to get the arc the code is

\calcLength(A,B){mylen} 
\draw[red,line width=1mm]  (A) -- ++(45:\mylen pt);  
\draw[blue] (A) -- ++(\mylen pt,0) arc (0:45:\mylen pt); 

For me it is more readable but it is a matter of taste

1
  • 1
    Completely agree. With calcLength the code is much more readable and avoiding the let syntax simplifies typing. 1 up! Oct 5, 2015 at 11:57
9

With the TikZ library math looks quite intuitive :)

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

\begin{document}
\begin{tikzpicture}
%Two points (A) and (B)
\coordinate (A) at (0,0);
\coordinate (B) at (2,2);

%--Computing the distance between (A) and (B)
%Creating a math coordinate
\tikzmath{coordinate \C;
%Storing coordinates difference
\C = (B)-(A); 
%Computing the length of C = (Cx,Cy) from its components Cx and Cy
%Note the length \distAB is in points (pt)
\distAB = sqrt((\Cx)^2+(\Cy)^2); 
}

%--Drawing 
%line A -- B
\draw (A) node [above] {A} -- (B) node[above] {B} node[midway]{\distAB pt};
%Circle with center in (A) and radius \distAB points
\draw (A) circle (\distAB pt);
\end{tikzpicture}

\end{document}

Note: instead of manually computing the norm \distAB = sqrt((\Cx)^2+(\Cy)^2);, you will see in the math TikZ library the function veclen(Vx,Vy). I discourage its use, because the precision is disappointingly low.

enter image description here

Additional solution in cm

It is quite bewildering that TikZ points accept per default lengths in cm (e.g., \coordinate (A) at (2,2) means (2cm,2cm)), but calculations of coordinates in tikzmath are performed and output in pt. For that reason, I have carried out tiny modifications in the code above so that all lengths are consistently represented in cm. (Credits for the \convertto macro go to Philippe Goutet)

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

\makeatletter
\def\convertto#1#2{\strip@pt\dimexpr #2*65536/\number\dimexpr 1#1}
\makeatother

\begin{document}
\begin{tikzpicture}
%Two points (A) and (B)
%Note: Default TikZ coordinates are centimeters
%      but inner computations are performed in pt
\coordinate (A) at (0,0); 
\coordinate (B) at (2,2); 

%--Computing the distance between (A) and (B)
%Creating a math coordinate
\tikzmath{coordinate \C;
%Storing coordinates difference
\C = (B)-(A); 
%Computing the length of C = (Cx,Cy) from its components Cx and Cy
%Note the length \distAB is in points (pt)
\distAB = sqrt((\Cx)^2+(\Cy)^2);
%Convert back to centimeters
\distAB = \convertto{cm}{\distAB pt};
}

%--Drawing 
%line A -- B
\draw (A) node [above] {A} -- (B) node[above] {B} node[midway]{\distAB cm};
%Circle with center in (A) and radius \distAB points
\draw (A) circle (\distAB);
\end{tikzpicture}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.