Draw circle in TikZ by specifying endpoint and distances instead of angles and radius

I think it is possible to let the calc library do most of the work. Then parameters can be given with or without dimensions:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc}
\tikzset{afro/.style args={(#1:#2)}{
  insert path={
    coordinate (@1)
    ($(@1)+(#1,#2)$) coordinate (@2)
    let \p1=($(@2)-(@1)$),
        \n1={(\x1*\x1+\y1*\y1)/(2*\y1)},
        \n2={acos((2*\x1*\y1)/(\x1*\x1+\y1*\y1))} in
    ($(@1)+(#1,0)$) arc (\n2:180-\n2:\n1)
}}}
\begin{document}
\begin{tikzpicture}
\draw (0,0) [afro=(2cm:1)];
\draw [red, ->] (0,0) -- (2cm,0);
\draw [red, ->] (0,0) -- (0,1cm);
\end{tikzpicture}
\end{document}

enter image description here


Part of the problem is doing math with distances. pgfmath uses 1=1pt to do calculations, while tikz typically uses 1=1cm when graphing. It has the ability to add units to \pgfmathresult, but all it does is take the first unit found while parsing.

This is a macro solution. You might be able to do this using a code key, if you are more comfortable with keys than macros.

\documentclass{article}
\usepackage{tikz}
%\usepackage{calc}% not needed inside tikz

\newcommand{\afro}[2]% #1 = a, #2 = b
 {\pgfextra{% needed inside a path
    \pgfmathparse{#1/1cm}%
    \let\a=\pgfmathresult
    \pgfmathparse{#2/1cm}%
    \let\b=\pgfmathresult
    \pgfmathparse{0.5*(\a*\a/\b + \b)}%
    \let\r=\pgfmathresult
    \pgfmathparse{acos(\a/\r)}%
    \let\angle=\pgfmathresult}%
  arc(\angle:180-\angle:\r cm)%
 }

\begin{document}

\begin{tikzpicture}
\draw[green] (0,0) arc (37:143:2.5cm);
\draw (0,0) node {$O$};
\end{tikzpicture}

\begin{tikzpicture}
\draw[red] (0,0) \afro{2cm}{1cm};
\draw (0,0) node {$O$};
\end{tikzpicture}

\end{document}

Here are some ideas.

The \ifpgfmathunitsdeclared test can be done after a \pgfmathparse operation (which \pgfmathsetmacro uses). The test will be true when at any place inside the mathematical evaluation something with a dimension has been used (either a TeX dimen or simply a statement like 2cm). If a unit is used either in #1 (a) or #2 (b) it is assumed that you want to draw your arc in the canvas coordinate system, otherwise in the local coordinate system. (Cf. (1, 2) vs (1cm, 2cm))

The calculation for the angle is also done before as it is used twice.

The /utils/exec key does nothing special, it justs executes the given code (like \pgfextra basically).


Note that the arc (…) path operator is deprecated. It is better to use the arc […] path operator, that way you can declare various options in an outer scope or use it in the every arc style.


More magic is needed if you want to use something like arc[a=2, b=1] without the auxiliary chord do style.

Code

\documentclass[tikz]{standalone}
\tikzset{
  chord/.style args={#1:#2}{
    /utils/exec=%
      \pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
      \ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
      \pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
    radius=\myTempVal, start angle=\myTempAng, end angle=180-\myTempAng},
  afro/.style={insert path={arc[chord={#1}]}},
  chord a/.initial=, chord b/.initial=,
  chord do/.style={chord={\pgfkeysvalueof{/tikz/chord a}:\pgfkeysvalueof{/tikz/chord b}}},
}

\begin{document}
\begin{tikzpicture}
\draw[green] (0,0) arc (37:143:2.5cm);
\draw (0,0) node {$O$};
\end{tikzpicture}

\begin{tikzpicture}
\draw[red] (0,0) [afro=2cm:1cm];
\draw (0,0) node {$O$};
\end{tikzpicture}

\begin{tikzpicture}
\draw[blue] (0,0) arc [chord=2:1];
\draw (0,0) node {$O$};
\end{tikzpicture}

\begin{tikzpicture}[chord b=1]
\foreach \a in {.1, .2, ..., 2}
  \draw[black] (0,0) arc [chord a=\a, chord do];
\draw (0,0) node {$O$};
\end{tikzpicture}
\end{document}