diff options
author | Karl Berry <karl@freefriends.org> | 2015-12-06 23:47:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-12-06 23:47:59 +0000 |
commit | 780c3bdde06307c3e02c609e6a1ed4d1665aef61 (patch) | |
tree | 368cd533e2f14db6f4503575a2d43ee971b317a3 /Master/texmf-dist/source | |
parent | 8fe2a43459967608180aff4cca4f63cd25c8ea5e (diff) |
ellipse (6dec15)
git-svn-id: svn://tug.org/texlive/trunk@39025 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/latex/ellipse/ellipse.dtx | 1238 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/ellipse/ellipse.ins | 71 |
2 files changed, 1309 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/ellipse/ellipse.dtx b/Master/texmf-dist/source/latex/ellipse/ellipse.dtx new file mode 100644 index 00000000000..c22bfe2a58f --- /dev/null +++ b/Master/texmf-dist/source/latex/ellipse/ellipse.dtx @@ -0,0 +1,1238 @@ +% \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{daan@microsoft.com}} +% +% \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} + \dimen@0.7071067\@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 + \dimen@0.0663\@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} + \dimen@57.29578\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 +
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/ellipse/ellipse.ins b/Master/texmf-dist/source/latex/ellipse/ellipse.ins new file mode 100644 index 00000000000..51abc729e9a --- /dev/null +++ b/Master/texmf-dist/source/latex/ellipse/ellipse.ins @@ -0,0 +1,71 @@ +%% +%% Copyright (C) 2015 +%% Daan Leijen +%% +%% This file is part of the LaTeX `ellipse' package. +%% ------------------------------------------------ +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% 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.3 or later is part of all distributions of LaTeX +%% version 2003/12/01 or later. +%% +%% This work has the LPPL maintenance status "author-maintained". +%% +%% In particular, NO PERMISSION is granted to modify the contents of this +%% file since it contains the legal notices that are placed in the files +%% it generates. +%% +%% This work consists of all files listed in manifest.txt. +%% +%% +%% --------------- start of docstrip commands ------------------ +%% + +\input docstrip + +\preamble + +Copyright (C) 2015 +Daan Leijen + +This work may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either version 1.3 +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.3 or later is part of all distributions of LaTeX +version 2003/12/01 or later. + +This work has the LPPL maintenance status "author-maintained". + +\endpreamble + +\keepsilent +\askforoverwritefalse + +\usedir{tex/latex/pict2e} + +\generate{\file{ellipse.sty}{\from{ellipse.dtx}{package}}} + +%\usepreamble\empty +%\usepostamble\empty + + +\Msg{***********************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the following} +\Msg{* files into a directory searched by TeX:} +\Msg{*} +\Msg{* All the files with extension `.sty' and `.def'} +\Msg{*} +\Msg{* To produce the documentation run the .dtx files through LaTeX.} +\Msg{*} +\Msg{* Happy TeXing} +\Msg{***********************************************************} + + +\endbatchfile
\ No newline at end of file |