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}
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}