% \iffalse meta-comment
%
% Copyright (C) 2015 Daan Leijen
% -------------------------------------------------------
%
% This file may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.2
% of this license or (at your option) any later version.
% The latest version of this license is in:
%
%
http://www.latex-project.org/lppl.txt
%
% and version 1.2 or later is part of all distributions of LaTeX
% version 1999/12/01 or later.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{ellipse.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{ellipse}
%<*package>
[2004/11/05 v1.0 .dtx ellipse file]
%</package>
%<package>\RequirePackage{pict2e}
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{graphicx}
\usepackage{ellipse}[2004/11/05]
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{hyperref}
\usepackage{lmodern}
\usepackage{xcolor}
\usepackage{wrapfig}
\newcommand\kk[1]{\iota_{#1}}
\newcommand\sk[1]{\rho_{#1}}
\newcommand\sint[1]{\textit{sint}_{#1}}
\newcommand\cost[1]{\textit{cost}_{#1}}
\newcommand\sign[1]{\pm_{#1}}
\newcommand\csqrt{\textit{csqrt}}
\renewcommand\cos{\textit{cos}}\renewcommand\sin{\textit{sin}}
\renewcommand\arctan{\textit{arctan}}\renewcommand\tan{\textit{tan}}
\renewcommand\max{\textit{max}}\renewcommand\sin{\textit{sin}}
\providecolor{teal}{HTML}{008080}
\providecolor{purple}{HTML}{800080}
\providecolor{navy}{HTML}{000080}
\providecolor{maroon}{HTML}{800000}
\providecolor{floralwhite}{HTML}{FFFAF0}
\providecolor{ivory}{HTML}{FFFFF0}
\providecolor{white}{HTML}{FFFFFF}
\providecolor{transparent}{named}{white}
\providecolor{gainsboro}{HTML}{DCDCDC}
\hypersetup{colorlinks=true,citecolor=navy,linkcolor=navy,urlcolor=navy,filecolor=navy,bookmarksdepth=3,bookmarksopenlevel=1}
\makeatletter
\DeclareRobustCommand*\package[2][]{%
\def\@tempa{#1}%
\ifx\@tempa\@empty
\textsf{#2}%
\else
\href{
http://mirrors.ctan.org/macros/latex/#1}{\textsf{#2}}%
\fi
}%
\DeclareRobustCommand*\pkgpicte{\package[contrib/pict2e/pict2e.pdf]{pict2e}}
\newsavebox{\@ebox}
\newcommand*\@unit[1]{\strip@pt\dimexpr#1\relax}%
\newcommand*\ellipbox[1]{%
\begingroup
\savebox{\@ebox}{#1}%
\setlength{\unitlength}{1pt}%
\hspace*{0.8ex}%
\begin{picture}(0,0)%
\put(\@unit{0.5\wd\@ebox},\@unit{0.5\ht\@ebox - 0.5\dp\@ebox}){%
\ellipse{\@unit{0.8ex + 0.5\wd\@ebox}}{\@unit{0.8ex + 0.5\ht\@ebox}}%
}%
\end{picture}%
\usebox{\@ebox}%
\hspace{0.8ex}%
\endgroup%
}
\makeatother
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
\setlength\emergencystretch{3em}
\DocInput{ellipse.dtx}
\PrintChanges
\setcounter{IndexColumns}{2}%
\PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{0}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
% Digits \0\1\2\3\4\5\6\7\8\9
% Exclamation \! Double quote \" Hash (number) \#
% Dollar \$ Percent \% Ampersand \&
% Acute accent \' Left paren \( Right paren \)
% Asterisk \* Plus \+ Comma \,
% Minus \- Point \. Solidus \/
% Colon \: Semicolon \; Less than \<
% Equals \= Greater than \> Question mark \?
% Commercial at \@ Left bracket \[ Backslash \\
% Right bracket \] Circumflex \^ Underscore \_
% Grave accent \` Left brace \{ Vertical bar \|
% Right brace \} Tilde \~}
%
%
% \changes{v1.0}{2015/03/24}{Initial version}
%
% \GetFileInfo{ellipse.dtx}
%
% \DoNotIndex{\newcommand,\renewcommand,\newenvironment,\renewenvironment}
% \DoNotIndex{\providecommand,\def,\edef,\let,\gdef,\xdef,\global,\newtoks}
% \DoNotIndex{\RequirePackage,\DeclareOption,\ProcessOptions,\ExecuteOptions}
% \DoNotIndex{\input,\InputIfFileExists}
% \DoNotIndex{\@ifdefinable,\@ifundefined,\@percentchar}
% \DoNotIndex{\AtBeginDocument,\AtEndOfPackage}
% \DoNotIndex{\PackageError,\PackageWarning,\PackageWarningNoLine,\PackageInfo}
% \DoNotIndex{\MessageBreak,\typeout}
%
% \DoNotIndex{\z@,\z@skip,\p@,\@ne,\tw@,\thr@@,\@iv,\two@fourteen,\strip@pt}
% \DoNotIndex{\the,\if,\else,\or,\fi,\ifnum,\ifdim,\ifcase,\ifodd}
% \DoNotIndex{\advance,\multiply,\divide}
% \DoNotIndex{\@tfor,\do}
% \DoNotIndex{\csname,\endcsname,\begingroup,\endgroup}
% \DoNotIndex{\expandafter,\afterassignment,\noexpand}
% \DoNotIndex{\@ovxx,\@ovyy,\@ovdx,\@ovdy}
% \DoNotIndex{\undefined,\dimexpr,\relax,\space,\protect,\begin}
% \DoNotIndex{\@tempdima,\@tempdimb,\@tempdimc,\@tempdimd,\dimen@,\@tempa}
% \DoNotIndex{\@tempswafalse,\@tempswatrue,\if@tempswa,\iffalse,\ifx,\ignorespaces}
%
% \title{The {\linethickness{0.6pt}\ellipbox{\textsf{ellipse}}} package}
% \author{Daan Leijen \\ \texttt{
[email protected]}}
%
% \maketitle
%
% \newcommand\pictexample[1]{%
% \setlength{\unitlength}{10pt}%
% \raisebox{-30pt}{\begin{picture}(6,8)%
% \linethickness{0.4pt}\roundjoin%
% \color{gainsboro}%
% \put(0,0){\multiput(0,0)(1,0){9}{\line(0,1){6}}%
% \multiput(0,0)(0,1){7}{\line(1,0){8}}%
% }%
% \put(0,0){\color{gray}%
% {\vector(1,0){8}}\put(-0.5,6.5){$y$}%
% {\vector(0,1){6}}\put(8.5,-0.5){$x$}%
% }%
% \color{black}%
% \linethickness{0.8pt}%
% #1\end{picture}}%
% }
%
% \section{Introduction}
%
% \LaTeX{} has many advanced graphics packages now, the most extensive are
% \href{
https://www.ctan.org/pkg/pgf}{\textsf{tikz}}
% and \href{
https://www.ctan.org/pkg/pstricks-base}{\textsf{pstricks}}.
% However, these are also large packages that take long to load and
% may not always work on all drivers. The standard \pkgpicte{} package removes many of the previous
% limitations of the `old' \LaTeX{} |picture| environment and makes it a \emph{lean
% and portable} alternative to the more full featured packages. However, even though it can
% draw circles and circle arcs well, it lacks the ability to draw ellipses and elliptical
% arcs. This package adds these functions on top of the standard \pkgpicte{} primitives
% (i.e. the |\cbezier| command).
%
% \section{Drawing ellipses}
%
% \noindent
% \DescribeMacro\ellipse
% \DescribeMacro{\ellipse*}
% \marg{x-radius}\marg{y-radius}\\
% \strut\\
% These commands draw an ellipse with the specified radi\"\i. The |\ellipse| command draws
% a stroked ellipse with the current |\linethickness| while |\ellipse*| draws a filled
% ellipse with the current |\color|. For example:
%
% \noindent\begin{minipage}{0.7\linewidth}%
% \begin{verbatim}
% \setlength{\unitlength}{10pt}%
% \begin{picture}(6,8)
% \linethickness{0.8pt}%
% \put(6,3){\color{teal}\ellipse*{2}{3}}%
% \put(3,3){\color{blue}\ellipse{3}{2}}%
% \end{picture}
% \end{verbatim}\end{minipage}
% \pictexample{%
% \put(6,3){\color{teal}\ellipse*{2}{3}}%
% \put(3,3){\color{blue}\ellipse{3}{2}}%
% }\\[2ex]
%
% \noindent
% \DescribeMacro\earc
% \DescribeMacro{\earc*}
% \oarg{start-angle$\rangle$|,|$\langle$end-angle}\marg{x-radius}\marg{y-radius}\\
% \strut\\
% These commands draw part of an ellipse with the specified radi\"\i.
% The |\earc| command draws
% a stroked elliptical arc with the current |\linethickness| while |\earc*| draws a filled
% elliptical `pie slice' with the current |\color|. The optional argument specifies a start and
% end-angle in degrees which must be between $-720$ and $720$ (but can be fractional).
% The endings of the arcs are determined by the \emph{cap} setting: |\buttcap| (default),
% |\roundcap| (add half disc), or |\squarecap| (add half square).
%
% \noindent\begin{minipage}{0.7\linewidth}%
% \begin{verbatim}
% \put(3,3){%
% \color{blue}\roundcap\earc[135,330]{3}{2}}%
% \put(6,3){%
% \color{teal}\earc*[-45,90]{2}{3}}%
% \end{verbatim}
% \end{minipage}
% \pictexample{%
% \put(3,3){\color{blue}\roundcap\earc[135,330]{3}{2}}%
% \put(6,3){\color{teal}\earc*[-45,90]{2}{3}}%
% }\\[2ex]
%
% \noindent
% \DescribeMacro\elliparc
% \oarg{initial}\marg{center-x}\marg{center-y}\marg{x-rad}\marg{y-rad}\marg{start-angle}\marg{end-angle}\\
%
% \noindent The core elliptical arc routine. These are to be used with path commands, like
% |\lineto|, |\moveto|, |\strokepath|, etc, and can draw an elliptical arc at any center point.
% The optional argument specifies the initial drawing
% action: the default is $0$ (|\lineto|) which draws a line to the arc starting point,
% the value $1$
% (|\moveto|) just moves to the starting point, and $2$ does nothing as an initial action.
% If the start angle is larger than the end angle, the arc is drawn clockwise, and otherwise
% anti-clockwise.\\[1ex]
%
% \noindent\begin{minipage}{0.7\linewidth}%
% \begin{verbatim}
% \elliparc[1]{3}{3}{3}{2}{90}{270}%
% \elliparc{5}{3}{2}{2}{-90}{90}%
% \closepath\strokepath
% \color{teal}%
% \moveto(1,3)
% \elliparc{3}{3}{2}{1}{-135}{135}%
% \closepath
% \fillpath
% \end{verbatim}\end{minipage}
% \pictexample{%
% \elliparc[1]{3}{3}{3}{2}{90}{270}%
% \elliparc{5}{3}{2}{2}{-90}{90}%
% \closepath\strokepath
% \color{teal}%
% \moveto(1,3)
% \elliparc{3}{3}{2}{1}{-135}{135}%
% \closepath
% \fillpath
% }\\[2ex]
%
% \noindent Note how the two initial arcs are automatically connected by a line
% segment from $(3,1)$ to $(5,1)$ (due to the default optional argument of $0$ that
% uses a |\lineto| command to the starting point of the arc). Similarly, we use
% such initial line segment and a |\closepath| to draw the triangular side of the
% inner ellipse.
%
% \subsection{Rotated ellipses}
%
% There is no direct command to rotate an ellipse but you can use the
% standard |\rotatebox| command from the \package[required/graphics/grfguide.pdf]{graphicx} package. For example:
%
% \noindent\begin{minipage}{0.7\linewidth}%
% \begin{verbatim}
% \put(3,3){%
% \rotatebox[origin=c]{45}{\ellipse{3}{2}}%
% }%
% \end{verbatim}\end{minipage}
% \pictexample{%
% \put(3,3){\rotatebox[origin=c]{45}{\ellipse{3}{2}}%
% }%
% }\\[2ex]
%
% \subsection{Using the picture environment inline}
%
% The standard \LaTeX{} |picture| environment is nowadays quite
% powerful and convenient. Read the latest \pkgpicte{} documentation
% and ``The unknown \emph{picture} environment'' \cite{picture} for more information.
% One particularly nice feature is that we
% can create a picture as |\begin{picture}(0,0)| to give it zero
% space. This can be used for example to define an |\ellipbox| command
% like:\\[1ex]
%
% \noindent\begin{minipage}{0.6\linewidth}%
% \begin{verbatim}
% Boxed numbers:
% \ellipbox{1}, \ellipbox{123}.
% \end{verbatim}
% \end{minipage}
% \begin{minipage}{0.38\linewidth}%
% Boxed numbers: \ellipbox{1}, \ellipbox{123}.
% \end{minipage}\\[1ex]
%
% \noindent We also used this command to draw the ellipse in the title
% of this article, and it is defined as:
% \begin{verbatim}
%\newsavebox{\@ebox}
%\newcommand*\@unit[1]{\strip@pt\dimexpr#1\relax}%
%\newcommand*\ellipbox[1]{%
% \begingroup
% \savebox{\@ebox}{#1}%
% \setlength{\unitlength}{1pt}%
% \hspace*{0.8ex}%
% \begin{picture}(0,0)%
% \put(\@unit{0.5\wd\@ebox},\@unit{0.5\ht\@ebox - 0.5\dp\@ebox}){%
% \ellipse{\@unit{0.8ex + 0.5\wd\@ebox}}{\@unit{0.8ex + 0.5\ht\@ebox}}%
% }%
% \end{picture}%
% \usebox{\@ebox}\hspace{0.25ex}\endgroup}
% \end{verbatim}
% \noindent This is not the best code possible but it hopefully gives you a good
% idea on how to implement your own boxes. Note the use of the |\@unit| macro
% to convert dimensions to units, which is also why we need to set the |\unitlength|
% to |1pt| here.
%
% \StopEventually{}
%
% \begin{thebibliography}{9}
% \raggedright
%
% \bibitem{abst} M.~Abramowitz and I.A.~Stegun: \textit{Handbook of Mathematical Functions},
% \url{people.math.sfu.ca/~cbm/aands}, 1964
%
% \bibitem{picture} Claudio Beccari: \emph{The unknown \emph{picture} environment},
% TUGBoat, vol. 33(1), 2012. \url{tug.org/TUGboat/tb33-1/tb103becc-picture.pdf}
%
% \bibitem{ellipse} Luc Maisonobe: \textit{Drawing an elliptical arc using polylines, quadratic or cubic B\'ezier lines.}
% \url{www.spaceroots.org/documents/ellipse/elliptical-arc.pdf}, 2003
%
% \bibitem{rajan:atan} S.~Rajan, Sichun Wang, R.~Inkol, and A.~Joyal: \textit{Efficient approximations for the arctangent function}.
% In Signal Processing Magazine, vol. 23(3), pages 108--111, May 2006
%
% \end{thebibliography}
%
% \clearpage
%
% \newcommand\abs[1]{\lvert #1\rvert}
% \newcommand\rarg[1]{$\langle$\textit{#1}$\rangle$}
% \newcommand\xellipse{\mathcal{E}}
%
% \section{Elliptical arcs as B\'ezier curves}
% \begin{figure}\begin{center}
% \setlength\unitlength{18pt}
% \begin{picture}(12,9)(-1.5,-0.5)%
% \linethickness{0.4pt}\roundjoin%
% \iffalse
% \color{gainsboro}%
% \put(0,0){%
% \multiput(-2,-1)(1,0){13}{\line(0,1){9}}%
% \multiput(-2,-1)(0,1){10}{\line(1,0){12}}%
% }%
% \fi
% \color{black}%
% \put(0,0){%
% \put(0,-0.5){\vector(0,1){8}}\put(8.5,-0.5){$x$}%
% \put(-1.5,0){\vector(1,0){11}}\put(-0.5,6.5){$y$}%
% }%
% \put(4,3.3){\color{navy}\earc{5}{3}
% \put(3,-2){$\xellipse$}%%
% \color{teal}%
% \put(-5.5,0){\line(1,0){11}}%
% \put(0,-3.5){\line(0,1){8}}%
% \put(3,0){\vector(-1,0){3}\vector(1,0){2}\raisebox{0.3ex}{$a$}}%
% \put(0,-1.5){\vector(0,1){1.5}\vector(0,-1){1.5}$\,b$}%
% \color{maroon}%
% \put(0,0){\moveto(0,0)\elliparc{0}{0}{5}{3}{30}{120}\closepath\strokepath}%
% {\linethickness{2pt}\earc[30,120]{5}{3}}%
% \put(3.7,2.2){$p_1$}\put(-2,3.1){$p_2$}%
% \put(2.25,2.92){\moveto(0,0)\lineto(1.35,-0.84)\strokepath\circle*{0.1}$\;q_1$}%
% \put(-0.075,3.22){\moveto(0,0)\lineto(-1.56,-0.39)\strokepath\circle*{0.1}$\,q_2$}%
% \color{black}
% \linethickness{0.2pt}\arc[0,30]{1}\arc[0,120]{2}%
% \put(1,0.2){$\alpha_1$}\put(1,1.8){$\alpha_2$}%
% }%
% \color{navy}\put(4,-0.3){$\,c_x$}\put(0,2.9){$\,c_y$}%
% %
% \end{picture}\end{center}
% \caption{Approximating an elliptical arc with a cubic B\'ezier curve. The center of the ellipse
% is at $(c_x,c_y)$ with a horizontal radius of $a$ and a vertical one $b$. The elliptical arc goes
% from $\alpha_1$ to $\alpha_2$ and is approximated with a thick red cubic B\'ezier curve. The curve
% starts at $p_1$ and ends in $p_2$ with two control points $q_1$ and $q_2$. The curve was drawn
% using the command \texttt{\textbackslash{}elliparc\{4\}\{3.3\}\{5\}\{3\}\{30\}\{120\}}.}
% \label{fig:ellipse}
% \end{figure}
% \begin{figure}
% \setlength\unitlength{20pt}\begin{center}
% \begin{picture}(12,8)(-1.5,-0.5)%
% \linethickness{0.4pt}\roundjoin%
% \iffalse
% \put(0,0){\color{gainsboro}%
% \multiput(-2,-1)(1,0){13}{\line(0,1){8}}%
% \multiput(-2,-1)(0,1){9}{\line(1,0){12}}%
% }%
% \fi
% \put(4,3){\color{navy}\earc{5}{3}\put(-4,1){$\xellipse$}\color{teal}%
% \put(-5.5,0){\line(1,0){11}}%
% \put(0,-3.5){\line(0,1){7}}%
% \put(-2,0){\vector(-1,0){3}\vector(1,0){2}\raisebox{0.3ex}{$a$}}%
% \put(0,-1.5){\vector(0,1){1.5}\vector(0,-1){1.5}$\,b$}%
% \color{black}%
% \put(0,0){\circle{6}}%
% \put(0,0){\vector(3.6,2.08){3.6}\vector(2.16,2.08){2.16}}%
% \put(0,0){\color{maroon}%
% \put(3.6,0){\line(0,1){2.08}\circle*{0.1}}%
% \put(3.2,-0.5){$a\cos(t_1)$}%
% \put(2.16,0){\line(0,1){2.08}\circle*{0.1}}%
% \put(1.3,-0.5){$\cos(t_1)$}%
% }%
% \linethickness{0.2pt}\arc[0,30]{1}\arc[0,43.9]{2}%
% \put(1,0.2){$\alpha_1$}\put(1.65,1.25){$t_1$}%
% }%
% %
% \end{picture}\end{center}
% \caption{The relation between the parametric angle $t_1$ and the angle $\alpha_1$ to the point on the ellipse.
% All points on the ellipse are defined by the parametric equation $\xellipse(t) = (c_x + a\cdot\cos(t), c_y + b\cdot\sin(t))$}
% \label{fig:parametric}
% \end{figure}
% %
% %
% Drawing an ellipse or part of an ellipse (\emph{elliptical arc}) using B\'ezier
% curves requires some math to determine the right control points of the B\'ezier curve.
% Figure~\ref{fig:ellipse} establishes some notation. We do not consider rotated
% ellipses here and always use $a$ for the $x$-radius and $b$ for the $y$-radius.
% We are interested in finding the B\'ezier curve between the $\alpha_1$ and
% $\alpha_2$ angles, which implies finding the starting
% point $p_1$, the end point $p_2$ and the control points $q_1$ and $q_2$.
%
% Each point on an ellipse is determined by the following parametric equation:
% \[ \xellipse(t) = (c_x + a\cdot\cos(t), c_y + b\cdot\sin(t)) \]
% where $t$ is the
% parametric angle. The parametric angle $t$ is just a property of the ellipse and has no
% `real' counterpart. Figure~\ref{fig:parametric} gives some helpful intuition how
% the $\alpha$ angles and $t$ angles are related: we can imagine drawing a unit circle inside
% an ellipse where for every $t$ angle on the unit circle we have a corresponding point
% and angle $\alpha$ on the ellipse. From the definition of $\xellipse$ it
% is straightforward to derive a parametric angle $t_i$ for some $\alpha_i$:
% \[ t_i = \arctan_2(\frac{\sin(\alpha_i)}{b},\frac{\cos(\alpha_i)}{a}) \]
%
% \noindent Given this relation, the start and end points of our curve are simply:
% \begin{align*}
% p_1 &= \xellipse(t_1)\\
% p_2 &= \xellipse(t_2)
% \end{align*}
%
% \noindent To be able to calculate optimal control points $q$ we need to also determine the
% tangent of each point on the ellipse, which is given by the derivative of $\xellipse$:
% \[ \xellipse'(t) = (-a\cdot\sin(t), b\cdot\cos(t)) \]
%
% \noindent
% The derivation of the optimal B\'ezier control points for an ellipse is quite involved,
% see~\cite{ellipse} for a nice overview.
% For a quadratic B\'ezier curve, it turns out the optimal control points are determined as:
% \begin{align*}
% q_1 &= p_1 + \tan(\frac{t_2 - t_1}{2})\cdot\xellipse'(t_1)\\
% &= p_2 - \tan(\frac{t_2 - t_1}{2})\cdot\xellipse'(t_2)
% \end{align*}
% %
% \noindent while for a cubic B\'ezier curve, one solution for optimal control points is:
% %
% \begin{align*}
% q_1 &= p_1 + \kappa\cdot\xellipse'(t_1)\\
% q_2 &= p_2 - \kappa\cdot\xellipse'(t_2)\\
% \kappa &= \sin(t_2 - t_1)\frac{\sqrt{4 + 3\tan^2(\frac{t_2 - t_1}{2})}-1}{3}
% \end{align*}
% \noindent We will use cubic bezier curves since they look best. However, a na\"\i{}ve implementation
% may be too expensive in \LaTeX: if we count the expensive operations, we need about 11 $\cos$/$\sin$
% operations, plus a $\sqrt{}$ and 2 $\arctan$ operations.
% %
% \subsection{Optimizing elliptic arc equations}
% Fortunately, we can improve upon this. First we note:
% \begin{flalign*}
% t_i &= \arctan_2(\frac{\sin(\alpha_i)}{b},\frac{\cos(\alpha_i)}{a}) & \hfill\\
% &= \arctan(\frac{a}{b}\tan(\alpha_i)) \\
% &= \arctan(\kk{i}) & \mbox{(introducing $\kk{i}$ for $\frac{a}{b}\tan(\alpha_i)$)}
% \end{flalign*}
% \noindent where we write $\kk{i}$ for $\frac{a}{b}\tan(\alpha_i)$. Now,
% \begin{flalign*}
% \cost{i} &= \cos(t_i)\\
% &= \cos(\arctan(\kk{i})) & \mbox{(geometry and pythagorean theorem)}\\
% &= \sign{i}\frac{1}{\sqrt{1 + \kk{i}^2}} \\
% \mbox{with}\\
% \sign{i} &= \textsf{if}\; \cos(\alpha_i) < 0\; \textsf{then}\; -\; \textsf{else}\; +
% \end{flalign*}
% Later we will see how we can efficiently calculate the square root term, but first
% do the same derivation for the $\sin$ function:
% \begin{flalign*}
% \sint{i}&= \sin(t_i) \\
% &= \sin(\arctan(\frac{a}{b}\tan(\alpha_i))) & \\
% &= \sin(\arctan(\kk{i})) \\
% &= \sign{i}\frac{\kk{i}}{\sqrt{1 + \kk{i}^2}}
% \end{flalign*}
% \noindent Note that the interaction between the $\sin$ and $\kk{i}$ term (whose sign is determined by $\tan(\alpha_i)$) allows us to reuse the sign function used for $\cost{i}$.
% %
% Using the previous equalities we can restate the parametric equations in terms of $\sint{i}$
% and $\cost{i}$:
% \begin{flalign*}
% \xellipse_i &= (c_x + a\cdot\cost{i}), c_y + b\cdot\sint{i}) \\
% \xellipse'_i &= (-a\cdot\sint{i}, b\cdot\cost{i})
% \end{flalign*}
% %
% \noindent This takes care of $p_1$ and $p_2$. The control points $q$ still need $\sin(t_2 - t_1)$ and $\tan(\frac{t_2 - t_1}{2})$.
% The halving rule on $\tan$ gives us:
% \[
% \tan(\frac{t_2 - t_1}{2}) = \frac{1 - \cos(t_2 - t_1)}{\sin(t_2 - t_1)} \mbox{\quad(\cite[page 71, 4.3.20]{abst})}
% \]
% \noindent So that leaves $\sin(t_2 - t_1)$ and $\cos(t_2 - t_1)$. Using the addition laws it follows:
% \begin{flalign*}
% \sin(t_2 - t_1) = \sint2\cost1 - \cost2\sint1 & \mbox{\quad(\cite[page 72, 4.3.16]{abst})}\\
% \cos(t_2 - t_1) = \cost2\cost1 + \sint2\sint1 & \mbox{\quad(\cite[page 72, 4.3.17]{abst})}
% \end{flalign*}
%
% \subsection{Circular square roots}
% \noindent Now, we only need two $\tan$ operations to calculate the initial $\kk{1}$ and $\kk{2}$ terms but we still have
% three square roots: $\sqrt{1 + \kk{i}^2}$ and $\sqrt{4 + 3\tan^2(\frac{t_2 - t_1}{2})}$.
% Fortunately, both have the form $\sqrt{x^2 + y^2}$. For this form, we can make a very good
% \begin{wrapfigure}[10]{o}{0.3\textwidth}
% \setlength\unitlength{3pt}
% \begin{picture}(30,30)(-15,-15)%
% \linethickness{0.4pt}\roundjoin%
% \iffalse
% \put(0,0){\color{gainsboro}%
% \multiput(-15,-15)(1,0){31}{\line(0,1){30}}%
% \multiput(-15,-15)(0,1){31}{\line(1,0){30}}%
% }%
% \fi
% \color{gainsboro}%
% \put(0,0){\put(0,-15){\line(0,1){30}}%
% \put(-15,0){\line(1,0){30}}%
% }%
% \color{black}%
% \put(0,0){\circle{20}\put(-9,3){$\,x^2 + y^2$}%
% \color{maroon}\moveto(14.14,0)\lineto(0,14.14)\lineto(-14.14,0)\lineto(0,-14.14)
% \closepath\strokepath
% \put(3,13){$\frac{1}{\sqrt{2}}(x+y)$}%
% \color{navy}\moveto(10,10)\lineto(-10,10)\lineto(-10,-10)\lineto(10,-10)
% \closepath\strokepath
% \put(6,-12){$\,\max(x,y)$}%
% }
% %
% \end{picture}\iffalse\caption{Estimating an initial value for $\sqrt{x^2+y^2}$}\fi
% \end{wrapfigure}
% initial guess for the square root, since this is the parametric equation for a circle.
% The two good initial guesses form a `square' and `diamond' around this circle, namely
% $\max(\abs{x},\abs{y})$ and $\frac{1}{\sqrt{2}}\abs{x+y}$. Each one can be superior depending if $x$ and $y$
% are close or not, but it can be shown that the best choice is always the largest of these.
% Using this guess as an initial seed, we can do a standard Newton-Raphson iteration to
% find a the square root where we only need 2 or 3 steps to achieve the desired precision.
% Let's define a `circular square root' function $\csqrt$ such that
% $\csqrt(x,y) \approx \sqrt{x^2 + y^2}$ as:
% \begin{align*}
% \csqrt(x,y) = &\textsf{let} & sqr & = x^2 + y^2 & \hfill \\
% & & x_0 & = \max(\abs{x},\abs{y},\frac{1}{\sqrt{2}}\abs{x+y}) & \\
% & & x_1 & = (x_0 + \frac{sqr}{x_0})/2 & \hspace{\textwidth}\\
% & & x_2 & = (x_1 + \frac{sqr}{x_1})/2 &\\
% & \textsf{in} & x_2 &
% \end{align*}
%
% \subsection{The optimized elliptical B\'ezier equations}
% \noindent Taking it all together, we get the following equations for a cubic B\'ezier curve approximation of an elliptical arc,
% where we assume as input the center point $(c_x,c_y)$, the $x$- and $y$-radius $(a,b)$, and a start and end angle
% $\alpha_1$ and $\alpha_2$. % It is assumed that $\alpha_1 \ne \alpha_2$ and $a \ge 0, b \ge 0$. Of course,
% with bezier curves one should build a full ellipse of parts where for each part $\rvert\alpha_1 - \alpha_2\lvert \le 90$.
% Given these parameters, the start and end point $p_1$ and $p_2$, and the control points $q_1$ and $q_2$ are
% defined as:
% \begin{flalign*}
% p_1 &= \xellipse_1 & \\
% p_2 &= \xellipse_2\\
% q_1 &= p_1 + \kappa\cdot\xellipse'_1\\
% q_2 &= p_2 - \kappa\cdot\xellipse'_2\\
% \xellipse_i &= (c_x + a\cdot\cost{i}, c_y + b\cdot\sint{i})\\
% \xellipse'_i &= (-a\cdot\sint{i}, b\cdot\cost{i})
% \end{flalign*}
% The $\cost{i}$ and $\sint{i}$ are calculated as:
% \begin{flalign*}
% \sint{i} & = \sign{i}\frac{\kk{i}}{\sk{i}} & \\
% \cost{i} & = \sign{i}\frac{1}{\sk{i}}
% \end{flalign*}
% with
% \begin{flalign*}
% \kk{i} &= \frac{a}{b}\tan(\alpha_i) & \\
% \sk{i} &= \csqrt(1,\kk{i}) \;\;(\approx \sqrt{1 + \kk{i}^2}) \\
% \sign{i} &= \textsf{if}\; \cos(\alpha_i) < 0\; \textsf{then}\; -\; \textsf{else}\; +
% \end{flalign*}
% And finally, the $\kappa$ term can be defined as:
% \begin{flalign*}
% \kappa &= \sint{21}\frac{\kappa_{sqrt}-1}{3} &
% \end{flalign*}
% with
% \begin{flalign*}
% \sint{21} & = \sint2\cost1 - \cost2\sint1 \;\;(=\sin(t_2 - t_1)) & \\
% \cost{21} & = \cost2\cost1 + \sint2\sint1 \;\;(=\cos(t_2 - t_1))\\
% \kappa_{tan} &= \frac{1 - \cost{21}}{\sint{21}} \;\;\mbox{(note: divides by zero if $\alpha_1 = \alpha_2$)}\\
% \kappa_{sqrt} &= \csqrt(\sqrt{4},\sqrt{3}\cdot\kappa_{tan}) \;\;(\approx \sqrt{4 + 3\kappa_{tan}^2})
% \end{flalign*}
%
%\section{Implementation}
%
% Generally, we use e-\TeX{} division to divide dimensions, where we
% divide \rarg{dim$_1$} by \rarg{dim$_2$} using:
% |\dimexpr 1pt * |\rarg{dim$_1$}|/|\rarg{dim$_2$}|\relax|
% since it keeps a 64-bit intermediate result for such `scaling' expressions.
% Note that both \rarg{dim}
% expressions occur in an integer context and \TeX{} will convert
% them to numbers automatically (i.e. in |sp| units).
%
% \subsection{Generic math and trigonometry routines}
%
% \begin{macro}{\pIIe@csedef}
% \marg{csname}\textit{pattern}\marg{body}\\
% Define a macro by a \textit{csname}. Just like the |\csedef| function
% from \textsf{etoolbox} package
% \begin{macrocode}
\providecommand*\pIIe@csedef[1]{\expandafter\edef\csname #1\endcsname}
% \end{macrocode}
% \end{macro}
%
%\begin{macro}{\pIIe@ellip@csqrt}
% \marg{dimen$_x$}\marg{dimen$_y$}\marg{dimreg$_{res}$}\\
% Calculates $res \approx \sqrt{x^2 + y^2}$ and caches previous results
% for efficiency.
%
% Overwrites |\@ovxx|,|\@ovyy|,|\@ovdx|,|\@ovdy|,|\@tempa|, and |\dimen@|.
% \begin{macrocode}
\newcommand*\pIIe@ellip@csqrt[3]{%
\@ovxx=#1\relax
\ifdim\@ovxx<\z@\@ovxx-\@ovxx\fi
\@ovyy=#2\relax
\ifdim\@ovyy<\z@\@ovyy-\@ovyy\fi
\edef\pIIe@csname{@csqrt(\number\@ovxx,\number\@ovyy)}%
\expandafter\ifx\csname\pIIe@csname\endcsname\relax
\pIIe@ellip@csqrt@%
\pIIe@csedef{\pIIe@csname}{\the\dimen@}%
#3\dimen@
\else
#3\dimexpr\csname\pIIe@csname\endcsname\relax
\fi
}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\pIIe@ellip@csqrt@}
% Internal routine: calculates |\dimen@| $\approx \sqrt{x^2 + y^2}$.
% where $x \ge 0$ and $y \ge 0$, and |\@ovxx| $=x$ and |\@ovyy| $=y$.
%
% Overwrites |\@ovdx|,|\@ovdy|, and |\@tempa|.
% \begin{macrocode}
\newcommand*\pIIe@ellip@csqrt@{%
% \end{macrocode}
% First determine $\max(x,y,\frac{1}{\sqrt{2}}(x+y))$ in |\dimen@|.
% Put the sum $x+y$ in |\@ovdx|.
% \begin{macrocode}
\@ovdx\@ovxx
\advance\@ovdx by \@ovyy
% \end{macrocode}
% Put initial guess in |\dimen@| $=\max(\abs{x},\abs{y},\frac{1}{\sqrt{2}}(x+y))$.
% \begin{macrocode}
\
[email protected]\@ovdx
\ifdim\dimen@<\@ovyy\dimen@\@ovyy\fi
\ifdim\dimen@<\@ovxx\dimen@\@ovxx\fi
% \end{macrocode}
% To prevent overflowing \TeX{} dimensions we only do
% a further Newton-Raphson approximation if the sum $x+y$ is less than 128pt.
% Otherwise, for our application, the initial guess is still very precise since $x \ll y$ in that case.
% \begin{macrocode}
\ifdim\@ovdx<128\p@
% \end{macrocode}
% Set |\@ovxx| to $x^2 + y^2$
% \begin{macrocode}
\edef\@tempa{\strip@pt\@ovxx}%
\@ovxx\@tempa\@ovxx
\edef\@tempa{\strip@pt\@ovyy}%
\@ovyy\@tempa\@ovyy
\advance\@ovxx by \@ovyy
% \end{macrocode}
% Do two steps of Newton-Raphson (should we do three?)
% \begin{macrocode}
\advance\dimen@ by \dimexpr1pt * \@ovxx/\dimen@\relax
\divide\dimen@ by 2%
\advance\dimen@ by \dimexpr1pt * \@ovxx/\dimen@\relax
\divide\dimen@ by 2%
\fi
% \end{macrocode}
% Result is |\dimen@|.
% \begin{macrocode}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pIIe@atan@}
%
% Approximate the $\arctan$ using
% \[x\cdot\frac{\pi}{4} - x \cdot (\abs{x} - 1) \cdot (0.2447 + 0.0663\cdot\abs{x})\]
% This approximation was described by Rajan et al.~\cite{rajan:atan}.
%
% The \cmd{pIIe@atan@} computes the arctan of |\dimen@| which must be between $-1$ and $1$, and stores it in |\dimen@| again.
% Overwrites |\@tempdim|(|a|,|b|,|c|,|d|),|\@tempa|, and |\dimen@|.
% \begin{macrocode}
\newcommand*\pIIe@atan@{%
% \end{macrocode}
% |\dimen@| contains $x$.
% \begin{macrocode}
\@tempdima\dimen@
% \end{macrocode}
% Set |\@dimtmpb| to $\abs{x}$
% \begin{macrocode}
\@tempdimb\@tempdima
\ifdim\@tempdimb<\z@\@tempdimb-\@tempdimb\fi
\
[email protected]\@tempdimb
\advance\dimen@ 0.2447pt\relax
\advance\@tempdimb -1pt\relax
\edef\@tempa{\strip@pt\@tempdimb}%
\dimen@\@tempa\dimen@
\edef\@tempa{\strip@pt\@tempdima}%
\dimen@\@tempa\dimen@
\dimen@-\dimen@
% \end{macrocode}
% Add $x\cdot\frac{\pi}{4}$ ($\approx 0.7853\cdot x$).
% \begin{macrocode}
\advance\dimen@ 0.7853\@tempdima
}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\pIIe@atantwo}
% \marg{dimen$_y$}\marg{dimen$_x$}\marg{dimreg$_{res}$}\\
% Calculate \rarg{res} $= \arctan_2(y,x)$ and caches the result for later use.
%
% Overwrites |\@tempdim|(|a|,|b|,|c|,|d|),|\@tempa|, and |\dimen@|.
% Both $y$ and $x$ must be dimensions.
% \begin{macrocode}
\newcommand*\pIIe@atantwo[3]{%
\edef\pIIe@csname{@atan2(\number\dimexpr#1\relax,\number\dimexpr#2\relax)}%
\expandafter\ifx\csname\pIIe@csname\endcsname\relax
\pIIe@atantwo@{#1}{#2}{#3}%
\pIIe@csedef{\pIIe@csname}{\the\dimexpr#3\relax}%
\else
#3\dimexpr\csname\pIIe@csname\endcsname\relax
\fi
}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\pIIe@atantwo@}
% \marg{dimen$_y$}\marg{dimen$_x$}\marg{dimreg$_{res}$}\\
% Calculate \rarg{res} $= \arctan_2(y,x)$.
% Overwrites |\@tempdim|(|a|,|b|,|c|,|d|),|\@tempa|, and |\dimen@|.
% Both $y$ and $x$ must be dimensions.
% \begin{macrocode}
\newcommand*\pIIe@atantwo@[3]{%
\@tempdima\dimexpr#2\relax
\@tempdimb\dimexpr#1\relax
% \end{macrocode}
% Handle extremes
% \begin{macrocode}
\ifdim\@tempdima=\z@\relax
\ifdim\@tempdimb>\z@\relax\dimen@90\p@
\else\ifdim\@tempdimb<\z@\relax\dimen@-90\p@
\else\dimen@0\p@
\fi\fi
\else
% \end{macrocode}
% Save angle adjustment term in |\@tempdimd|.
% \begin{macrocode}
\@tempdimd\z@
\ifdim\@tempdima<\z@\relax
\ifdim\@tempdimb<\z@\relax\@tempdimd-180\p@
\else\@tempdimd180\p@
\fi
\fi
% \end{macrocode}
% Divide $\frac{y}{x}$ and check if $-1 \le \frac{y}{x} \le 1$.
% \begin{macrocode}
\dimen@\dimexpr1pt * \@tempdimb/\@tempdima\relax
\@tempdimc\dimen@
\ifdim\@tempdimc<\z@\relax\@tempdimc-\@tempdimc\fi
\ifdim\@tempdimc>\p@\relax
% \end{macrocode}
% Use the equality $\arctan(x) = \pm\frac{1}{2}\pi - \arctan(\frac{1}{x})$
% to stay within the valid domain of |\pIIe@atan@|. The sign $\pm$ is
% positive when $x \ge 0$ and negative otherwise.
% \begin{macrocode}
\dimen@\dimexpr1pt * \@tempdima/\@tempdimb\relax
\ifdim\dimen@<\z@\relax\def\@tempsign{-}\else\def\@tempsign{}\fi
\pIIe@atan@
\dimen@-\dimen@
\advance\dimen@ by \@tempsign1.5707pt\relax
\else
\pIIe@atan@
\fi
% \end{macrocode}
% And convert back to degrees ($\frac{180}{\pi} \approx 57.29578$)
% \begin{macrocode}
\
[email protected]\dimen@
% \end{macrocode}
% Apply angle adjustment
% \begin{macrocode}
\advance\dimen@ by \@tempdimd
\fi
#3\dimen@%
}
% \end{macrocode}
% \end{macro}
% \subsection{Sub routines for drawing an elliptical arc}
%
%
% \begin{macro}{\pIIe@noneto}
% \marg{dimen$_x$}\marg{dimen$_y$}\\
% Ignores its arguments. Used as a no-op instead of |\pIIe@lineto| or |pIIe@moveto|.
% \begin{macrocode}
\newcommand*\pIIe@noneto[2]{}
% \end{macrocode}
% \end{macro}
%
%\begin{macro}{\pIIe@ellip@sincost@}
% \marg{$\alpha_i$}\marg{$i$ = |one| or |two|}\\
% Calculate $\sint{i}$ and $\cost{i}$ into the |\@ellip|(|sin|/|cos|)$i$.
% Assumes |\@ellipratio| $=\frac{a}{b}$.
% \begin{macrocode}
\newcommand*\pIIe@ellip@sincost@[2]{%
% \end{macrocode}
% Put the $\sin(\alpha_i)$ and $\cos(\alpha_i)$ into |\@tempdima| and |\@tempdimb|.
% \begin{macrocode}
\CalculateSin{#1}%
\CalculateCos{#1}%
\@tempdima\UseSin{#1}\p@
\@tempdimb\UseCos{#1}\p@
% \end{macrocode}
% Check for extremes where $\tan = \pm\infty$.
% \begin{macrocode}
\ifdim\@tempdima=\p@\relax
\pIIe@csedef{@ellipsin#2}{1}%
\pIIe@csedef{@ellipcos#2}{0}%
\else\ifdim\@tempdima=-\p@\relax
\pIIe@csedef{@ellipsin#2}{-1}%
\pIIe@csedef{@ellipcos#2}{0}%
\else
% \end{macrocode}
% Calculate $\kk{i}$ in |\@tempdimc| and $\sqrt{1 + \kk{i}^2}$ in |\@tempdimd|,
% and derive $\sint{i}$ and $\cost{i}$.
% \begin{macrocode}
\@tempdimc\@ellipratio\dimexpr1pt * \@tempdima/\@tempdimb\relax
%\typeout{ i#2=\the\@tempdimc, sin(#1)=\the\@tempdima}%
\pIIe@ellip@csqrt{\p@}{\@tempdimc}\@tempdimd
\ifdim\@tempdimb<\z@\relax\@tempdimd-\@tempdimd\fi
\pIIe@csedef{@ellipsin#2}{\strip@pt\dimexpr1pt * \@tempdimc/\@tempdimd\relax}%
\pIIe@csedef{@ellipcos#2}{\strip@pt\dimexpr1pt * \p@/\@tempdimd\relax}%
\fi\fi
}
% \end{macrocode}
% \end{macro}
%\begin{macro}{\pIIe@ellip@sincost}
% \marg{$\alpha_1$}\marg{$\alpha_2$}\\
% Calculate $\sint{i}$ and $\cost{i}$ into the |\@ellip|(|sin|/|cos|)(|one|/|two|).
% Assumes |\@ovro|$=a$ and |\@ovri|$=b$ with $b \ne 0$.
% \begin{macrocode}
\newcommand*\pIIe@ellip@sincost[2]{%
% \end{macrocode}
% Set |\@ellipratio| to the ratio $\frac{a}{b}$.
% \begin{macrocode}
%\typeout{ calc sin cos: angles (#1,#2), radii: (\the\@ovro,\the\@ovri)}%
\edef\@ellipratio{\strip@pt\dimexpr1pt * \@ovro/\@ovri\relax}%
% \end{macrocode}
% And calculate $\sint{i}$ and $\cost{i}$
% \begin{macrocode}
\pIIe@ellip@sincost@{#1}{one}%
\pIIe@ellip@sincost@{#2}{two}%
%\typeout{ sincos(a=#1)=(\@ellipsinone,\@ellipcosone), sincos(a=#2)=(\@ellipsintwo,\@ellipcostwo), }%
}
% \end{macrocode}
% \end{macro}
%
%
%\begin{macro}{\pIIe@omega}
% \marg{$i$ = |one| or |two|}\\
% Calculates $\xellipse_i$ into |\@tempdima| and |\@tempdimb|.
% Assumes |\@ovro|$=a$ and |\@ovri|$=b$.
% \begin{macrocode}
\newcommand*\pIIe@omega[3]{%
\@tempdima\csname @ellipcos#3\endcsname\@ovro
\advance\@tempdima by #1\relax
\@tempdimb\csname @ellipsin#3\endcsname\@ovri
\advance\@tempdimb by #2\relax
}
% \end{macrocode}
% \end{macro}
%\begin{macro}{\pIIe@omegai}
% \marg{$i$ = |one| or |two|}\\
% Calculates $\xellipse'_i$ into |\@tempdimc| and |\@tempdimd|.
% Assumes |\@ovro|$=a$ and |\@ovri|$=b$.
% \begin{macrocode}
\newcommand*\pIIe@omegai[1]{%
\@tempdimc\csname @ellipsin#1\endcsname\@ovro
\@tempdimc-\@tempdimc
\@tempdimd\csname @ellipcos#1\endcsname\@ovri
}
% \end{macrocode}
% \end{macro}
%\begin{macro}{\pIIe@ellip@kappa}
% Calculates $\kappa$, expects |\@ellip|(|sin|/|cos|)(|one|/|two|) to be defined.
% \begin{macrocode}
\newcommand*\pIIe@ellip@kappa{%
% \end{macrocode}
% Calculate $\sint{21}$ and $\cost{21}$ in |\@tempdima| and |\@tempdimb|.
% \begin{macrocode}
\@ovyy\@ellipsinone\p@
\@ovxx\@ellipcosone\p@
\@tempdima\@ellipcostwo\@ovyy
\@tempdima-\@tempdima
\advance\@tempdima by \@ellipsintwo\@ovxx
\@tempdimb\@ellipcostwo\@ovxx
\advance\@tempdimb by \@ellipsintwo\@ovyy
% \end{macrocode}
% First test if $\sint{21} = 0$ to prevent division by zero. In that
% case, it must have been that $\alpha_1 = \alpha_2$ and we set $\kappa$ to zero
% so it the control points become equal to the start and end point.
% \begin{macrocode}
\ifdim\@tempdima=\z@\relax
\edef\@ellipkappa{0}%
\else
% \end{macrocode}
% Calculate $\kappa_{tan}$ in |\dimen@|
% \begin{macrocode}
\dimen@\dimexpr1pt - \@tempdimb\relax
\dimen@\dimexpr1pt * \dimen@/\@tempdima\relax
% \end{macrocode}
% Calculate $\kappa_{sqrt}$ in |\dimen@|
% \begin{macrocode}
\pIIe@ellip@csqrt{2\p@}{1.73205\dimen@}{\dimen@}%
% \end{macrocode}
% Calculate $\kappa$ in |\dimen@|
% \begin{macrocode}
\advance\dimen@ by -\p@
\divide\dimen@ by 3%
\edef\@tempa{\strip@pt\@tempdima}%
\dimen@\@tempa\dimen@
\edef\@ellipkappa{\strip@pt\dimen@}%
\fi
%\typeout{ calculated kappa: \@ellipkappa}%
}
% \end{macrocode}
% \end{macro}
% \subsection{Core routines for drawing elliptical arcs}
%
%\begin{macro}{\pIIe@elliparc@}
% \oarg{start}\marg{$c_x$}\marg{$c_y$}\marg{$\alpha_1$}\marg{$\alpha_2$}\\
% Assumes that the radii are set as |\@ovro|$=a$ and |\@ovri|$=b$.
% This is the main routine for drawing an elliptic arc, where $\abs{\alpha_2 - \alpha_1}\,\le 90$.
% \begin{macrocode}
\newcommand*\pIIe@elliparc@[5]{%
%\typeout{elliparc: #1, center: (#2, #3), radius (\the\@ovro, \the\@ovri),angle (#4, #5)}%
% \end{macrocode}
% Define initial action: 0 (lineto), 1(moveto), or 2 (nothing)
% \begin{macrocode}
\ifcase #1\relax
\let\@ellip@startto\pIIe@lineto
\or \let\@ellip@startto\pIIe@moveto
\or \let\@ellip@startto\pIIe@noneto%
\else\PackageWarning{ellipse}{Illegal initial action in \protect\elliparc: %
must be one of 0 (lineto), 1 (moveto) or 2 (do nothing) but I got: #1}%
\fi
% \end{macrocode}
% Perform just the start action if the radii are zero
% \begin{macrocode}
\ifdim\@ovro=\z@\relax\@ovri\z@\fi
\ifdim\@ovri=\z@\relax
\@ellip@startto{#2}{#3}%
\else
% \end{macrocode}
% Calculate $\sint{i}$ and $\cost{i}$ first into the |\@ellip|(|sin|/|cos|)(|one|/|two|) registers.
% \begin{macrocode}
\pIIe@ellip@sincost{#4}{#5}%
% \end{macrocode}
% And draw..
% \begin{macrocode}
\pIIe@elliparc@draw{#2}{#3}%
\fi
}
% \end{macrocode}
% \end{macro}
%
%\begin{macro}{\pIIe@elliparc@t}
% \oarg{start}\marg{$c_x$}\marg{$c_y$}\marg{$t_1$}\marg{$t_2$}\\
% Assumes that the radii are set as |\@ovro|$=a$ and |\@ovri|$=b$.
% Moreover, this routine take $t_1$ and $t_2$ as the angles of the ellipse equation (instead of real angles $\alpha_i$).
% This routine is mainly for other libraries that may already have computed the $t$ angles
% and need a bit more efficiency.
% \begin{macrocode}
\newcommand*\pIIe@elliparc@t[5]{%
% \end{macrocode}
% Define initial action: 0 (lineto), 1(moveto), or 2 (nothing)
% \begin{macrocode}
\ifcase #1\relax
\let\@ellip@startto\pIIe@lineto
\or \let\@ellip@startto\pIIe@moveto
\or \let\@ellip@startto\pIIe@noneto%
\else\PackageWarning{ellipse}{Illegal initial action in \protect\elliparc: %
must be one of 0 (lineto), 1 (moveto) or 2 (do nothing) but I got: #1}%
\fi
% \end{macrocode}
% Perform just the start action if the radii are zero
% \begin{macrocode}
\ifdim\@ovro=\z@\relax\@ovri\z@\fi
\ifdim\@ovri=\z@\relax
\@ellip@startto{#2}{#3}%
\else
% \end{macrocode}
% Calculate $\sint{i}$ and $\cost{i}$ first into the |\@ellip|(|sin|/|cos|)(|one|/|two|) registers.
% \begin{macrocode}
\CalculateSin{#4}\CalculateCos{#4}%
\edef\@ellipsinone{\UseSin{#4}}%
\edef\@ellipcosone{\UseCos{#4}}%
\CalculateSin{#5}\CalculateCos{#5}%
\edef\@ellipsintwo{\UseSin{#5}}%
\edef\@ellipcostwo{\UseCos{#5}}%
% \end{macrocode}
% And draw..
% \begin{macrocode}
\pIIe@elliparc@draw{#2}{#3}%
\fi
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{pIIe@elliparc@draw}
% \marg{$c_x$}\marg{$c_y$}\\
% Expects $a =$|\@ovro|, $b$ = |\@ovri|, and |\@ellip|(|sin|/|cos|)(|one|/|two|) defined.
% |\@ellipstarto| should contain the initial drawing action and is called with an initial
% $x$ and $y$ coordinate (usually equal to |\pIIe@lineto|,|\pIIe@moveto|, or |pIIe@noneto|).
% \begin{macrocode}
\newcommand*\pIIe@elliparc@draw[2]{%
% Calculate $\kappa$.
% \begin{macrocode}
\pIIe@ellip@kappa%
% \end{macrocode}
% Now we are ready to compute the control points. First $p_1$.
% \begin{macrocode}
\pIIe@omega{#1}{#2}{one}%
%\typeout{ point one: (\the\@tempdima,\the\@tempdimb)}%
% \end{macrocode}
% The coordinates are added to the path if and how necessary:
% \begin{macrocode}
\@ellip@startto\@tempdima\@tempdimb
% \end{macrocode}
% Add control point $q_1$
% \begin{macrocode}
\pIIe@omegai{one}%
\advance\@tempdima by \@ellipkappa\@tempdimc
\advance\@tempdimb by \@ellipkappa\@tempdimd
\pIIe@add@nums\@tempdima\@tempdimb
%\typeout{ control one: (\the\@tempdima,\the\@tempdimb)}%
% \end{macrocode}
% Calculate $p_2$
% \begin{macrocode}
\pIIe@omega{#1}{#2}{two}%
% \end{macrocode}
% Add control point $q_1$
% \begin{macrocode}
\pIIe@omegai{two}%
\@tempdimc\@ellipkappa\@tempdimc
\@tempdimd\@ellipkappa\@tempdimd
\@tempdimc-\@tempdimc
\@tempdimd-\@tempdimd
\advance\@tempdimc by \@tempdima
\advance\@tempdimd by \@tempdimb
\pIIe@add@nums\@tempdimc\@tempdimd
%\typeout{ control two: (\the\@tempdimc,\the\@tempdimd)}%
% \end{macrocode}
% And finally add $p_2$ to the path
% \begin{macrocode}
\pIIe@add@CP\@tempdima\@tempdimb
%\typeout{ point two: (\the\@tempdima,\the\@tempdimb)}%
\pIIe@addtoGraph\pIIe@curveto@op
}
% \end{macrocode}
% \end{macro}
%
%
% \subsection{Normalizing elliptical arcs}
%
% \begin{macro}{pIIe@elliparc}
% \begin{macro}{pIIe@@elliparc}
% \oarg{start}\marg{$c_x$}\marg{$c_y$}\marg{a}\marg{b}\marg{$\alpha_1$}\marg{$\alpha_2$}\\
% \strut\\
% These two macros check the arguments and normalize the angles.
% \begin{macrocode}
\newcommand*\pIIe@elliparc[7][0]{%
% \end{macrocode}
% Store the radii in registers, where |\@ovro|$=a$ and |\@ovri|$=b$.
% \begin{macrocode}
\@ovro #4\relax
\@ovri #5\relax
\iffalse%dim\@ovro=\@ovri
% \end{macrocode}
% Call the circular arc routine if the x- and y-radius are equal
% \begin{macrocode}
\pIIe@arc[#1]{#2}{#3}{#4}{#6}{#7}
\else
% \end{macrocode}
% Normalize angles such that the arc angle $\abs{\alpha_2 - \alpha_1}\,\le 720$.
% Store the arc angle in |\@arclen|.
% \begin{macrocode}
\ifdim \@ovro<\z@ \pIIe@badcircarg\else
\ifdim \@ovri<\z@ \pIIe@badcircarg\else
\@arclen #7\p@ \advance\@arclen -#6\p@
\ifdim \@arclen<\z@ \def\@tempsign{-}\else\def\@tempsign{}\fi
\ifdim \@tempsign\@arclen>720\p@
\PackageWarning {ellipse}{The arc angle is reduced to -720..720}%
\@whiledim \@tempsign\@arclen>720\p@ \do {\advance\@arclen-\@tempsign360\p@}%
\@tempdima #6\p@ \advance\@tempdima \@arclen
\edef\@angleend{\strip@pt\@tempdima}%
\pIIe@@elliparc{#1}{#2}{#3}{#6}{\@angleend}%
\else
\pIIe@@elliparc{#1}{#2}{#3}{#6}{#7}%
\fi
\fi
\fi
\fi
}
% \end{macrocode}
% |\pIIe@@elliparc| divides the total angle in parts of at most $90$ degrees.
% Assumes |\@ovro|$=a$ and |\@ovri|$=b$, and |\@arclen| the arc angle, with |\@tempsign|
% sign of the arc angle.
% \begin{macrocode}
\newcommand*\pIIe@@elliparc[5]{%
\begingroup
\ifdim \@tempsign\@arclen>90\p@
% \end{macrocode}
% If the arc angle is too large, the arc is recursively
% divided into 2 parts until the arc angle is at most 90~degrees.
% \begin{macrocode}
\divide\@arclen 2%
\@tempdima #4\p@\advance\@tempdima by \@arclen
\edef\@anglemid{\strip@pt\@tempdima}%
\def\@tempa{\pIIe@@elliparc{#1}{#2}{#3}{#4}}%
\expandafter\@tempa\expandafter{\@anglemid}%
\def\@tempa{\pIIe@@elliparc{2}{#2}{#3}}%
\expandafter\@tempa\expandafter{\@anglemid}{#5}%
\else
% \end{macrocode}
% The arc angle is smaller than 90 degrees.
% \begin{macrocode}
\pIIe@elliparc@{#1}{#2}{#3}{#4}{#5}%
\fi
\endgroup
}%
% \end{macrocode}
% \end{macro}
%\end{macro}
% \subsection{Drawing elliptical arcs}
%
%\begin{macro}{\elliparc}
%\begin{macro}{\pIIeelliparc}
% \oarg{start}\marg{center-x}\marg{center-y}\marg{radius-x}\marg{radius-y}\marg{start-angle}\marg{end-angle}\\
% \strut\\
% The main elliptical arc drawing routine. We start with |\pIIeelliparc| to avoid conflicts with
% other packages.
% \begin{macrocode}
\newcommand*\pIIeelliparc[7][0]{%
\@killglue
\pIIe@elliparc[#1]{#2\unitlength}{#3\unitlength}{#4\unitlength}{#5\unitlength}{#6}{#7}%
\ignorespaces%
}
\ifx\undefined\elliparc\else
\PackageWarning{ellipse}{\protect\elliparc\space is redefined}%
\fi
\let\elliparc\pIIeelliparc
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\earc}
% \begin{macro}{\earc*}
% |[|\rarg{$\alpha_0$}|,|\rarg{$\alpha_1$}|]|\marg{radius-x}\marg{radius-y}\\
% \strut\\
% The \cmd{\earc} command generalizes the standard \cmd{\arc} with both
% a $x$- and $y$-radius. The |\earc*| version draws a filled elliptical arc while
% |\earc| only strokes the elliptical arc. Both take an optional comma separated pair of
% angles which specify the initial and final angle ($0$ and $360$ by default).
% We start with \cmd{\pIIeearc} to avoid conflicts with otherpackages.
% \begin{macrocode}
\newcommand*\pIIeearc
{\@ifstar{\@tempswatrue\pIIe@earc@}{\@tempswafalse\pIIe@earc@}}
\newcommand*\pIIe@earc@[3][0,360]{\pIIe@earc@@(#1){#2}{#3}}
\def\pIIe@earc@@(#1,#2)#3#4{%
\if@tempswa
\pIIe@moveto\z@\z@
\pIIe@elliparc{\z@}{\z@}{#3\unitlength}{#4\unitlength}{#1}{#2}%
\pIIe@closepath\pIIe@fillGraph
\else
\pIIe@elliparc[1]{\z@}{\z@}{#3\unitlength}{#4\unitlength}{#1}{#2}%
\pIIe@strokeGraph
\fi}
\ifx\undefined\earc\else
\PackageWarning{ellipse}{\protect\earc\space is redefined}%
\fi
\let\earc\pIIeearc
% \end{macrocode}
% \end{macro}
% \end{macro}
% \begin{macro}{\ellipse}
% \begin{macro}{\ellipse*}
% \marg{radius-x}\marg{radius-y}\\
% \strut\\
% The \cmd{\ellipse} draws an ellipse with the specified $x$- and $y$-radius.
% The |\ellipse*| version draws a filled ellipse.
% We start with \cmd{\pIIeellipse} to avoid conflicts with other packages.
% The implementation redirects immediately to |earc| which generalized this command.
% \begin{macrocode}
\newcommand*\pIIeellipse
{\@ifstar{\@tempswatrue\pIIe@earc@}{\@tempswafalse\pIIe@earc@}}
\let\ellipse\pIIeellipse
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \Finale
\endinput