diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-11 23:51:12 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-11 23:51:12 +0000 |
commit | 49110d0df1b2a5e1e4d88f22fb3e691ad679a63a (patch) | |
tree | 96dae2e8b8463fd5bdfa2ee02c23f40809c88c18 /Master/texmf-dist/source/latex/bez123/bez123.dtx | |
parent | 046a53eeb5a85347ebf6d69637034ebf90d155a6 (diff) |
trunk/Master/texmf-dist/source/latex/bez123
git-svn-id: svn://tug.org/texlive/trunk@158 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/bez123/bez123.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/bez123/bez123.dtx | 1818 |
1 files changed, 1818 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/bez123/bez123.dtx b/Master/texmf-dist/source/latex/bez123/bez123.dtx new file mode 100644 index 00000000000..042c208347b --- /dev/null +++ b/Master/texmf-dist/source/latex/bez123/bez123.dtx @@ -0,0 +1,1818 @@ +% \iffalse meta-comment +% +% bez123.dtx +% Author: Peter Wilson (CUA and NIST) +% peter.r.wilson@boeing.com +% +% Copyright 1998 Peter R. Wilson +% +% This program is provided under the terms of the +% LaTeX Project Public License distributed from CTAN +% archives in directory macros/latex/base/lppl.txt. +% +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{bez123} +\EnableCrossrefs +\CodelineIndex +\setcounter{StandardModuleDepth}{1} +\begin{document} + \DocInput{bez123.dtx} +\end{document} +%</driver> +% +% \fi +% +% \CheckSum{990} +% +% \DoNotIndex{\',\.,\@M,\@@input,\@addtoreset,\@arabic,\@badmath} +% \DoNotIndex{\@centercr,\@cite} +% \DoNotIndex{\@dotsep,\@empty,\@float,\@gobble,\@gobbletwo,\@ignoretrue} +% \DoNotIndex{\@input,\@ixpt,\@m} +% \DoNotIndex{\@minus,\@mkboth,\@ne,\@nil,\@nomath,\@plus,\@set@topoint} +% \DoNotIndex{\@tempboxa,\@tempcnta,\@tempdima,\@tempdimb} +% \DoNotIndex{\@tempswafalse,\@tempswatrue,\@viipt,\@viiipt,\@vipt} +% \DoNotIndex{\@vpt,\@warning,\@xiipt,\@xipt,\@xivpt,\@xpt,\@xviipt} +% \DoNotIndex{\@xxpt,\@xxvpt,\\,\ ,\addpenalty,\addtolength,\addvspace} +% \DoNotIndex{\advance,\Alph,\alph} +% \DoNotIndex{\arabic,\ast,\begin,\begingroup,\bfseries,\bgroup,\box} +% \DoNotIndex{\bullet} +% \DoNotIndex{\cdot,\cite,\CodelineIndex,\cr,\day,\DeclareOption} +% \DoNotIndex{\def,\DisableCrossrefs,\divide,\DocInput,\documentclass} +% \DoNotIndex{\DoNotIndex,\egroup,\ifdim,\else,\fi,\em,\endtrivlist} +% \DoNotIndex{\EnableCrossrefs,\end,\end@dblfloat,\end@float,\endgroup} +% \DoNotIndex{\endlist,\everycr,\everypar,\ExecuteOptions,\expandafter} +% \DoNotIndex{\fbox} +% \DoNotIndex{\filedate,\filename,\fileversion,\fontsize,\framebox,\gdef} +% \DoNotIndex{\global,\halign,\hangindent,\hbox,\hfil,\hfill,\hrule} +% \DoNotIndex{\hsize,\hskip,\hspace,\hss,\if@tempswa,\ifcase,\or,\fi,\fi} +% \DoNotIndex{\ifhmode,\ifvmode,\ifnum,\iftrue,\ifx,\fi,\fi,\fi,\fi,\fi} +% \DoNotIndex{\input} +% \DoNotIndex{\jobname,\kern,\leavevmode,\let,\leftmark} +% \DoNotIndex{\list,\llap,\long,\m@ne,\m@th,\mark,\markboth,\markright} +% \DoNotIndex{\month,\newcommand,\newcounter,\newenvironment} +% \DoNotIndex{\NeedsTeXFormat,\newdimen} +% \DoNotIndex{\newlength,\newpage,\nobreak,\noindent,\null,\number} +% \DoNotIndex{\numberline,\OldMakeindex,\OnlyDescription,\p@} +% \DoNotIndex{\pagestyle,\par,\paragraph,\paragraphmark,\parfillskip} +% \DoNotIndex{\penalty,\PrintChanges,\PrintIndex,\ProcessOptions} +% \DoNotIndex{\protect,\ProvidesClass,\raggedbottom,\raggedright} +% \DoNotIndex{\refstepcounter,\relax,\renewcommand,\reset@font} +% \DoNotIndex{\rightmargin,\rightmark,\rightskip,\rlap,\rmfamily,\roman} +% \DoNotIndex{\roman,\secdef,\selectfont,\setbox,\setcounter,\setlength} +% \DoNotIndex{\settowidth,\sfcode,\skip,\sloppy,\slshape,\space} +% \DoNotIndex{\symbol,\the,\trivlist,\typeout,\tw@,\undefined,\uppercase} +% \DoNotIndex{\usecounter,\usefont,\usepackage,\vfil,\vfill,\viiipt} +% \DoNotIndex{\viipt,\vipt,\vskip,\vspace} +% \DoNotIndex{\wd,\xiipt,\year,\z@} +% +% \def\fileversion{v1.1} +% \def\filedate{1998/10/14} +% \newcommand*{\Lpack}[1]{\textsf {#1}} ^^A typest a package +% \newcommand*{\Lopt}[1]{\textsf {#1}} ^^A typeset an option +% \newcommand*{\file}[1]{\texttt {#1}} ^^A typeset a file +% \newcommand*{\Lcount}[1]{\textsl {\small#1}} ^^A typeset a counter +% \newcommand*{\pstyle}[1]{\textsl {#1}} ^^A typeset a pagestyle +% \newcommand*{\Lenv}[1]{\texttt {#1}} ^^A typeset an environment +% \newcommand{\eqref}[1]{equation~(\ref{#1})} ^^A typeset ref to an equation +% +% \title{The \Lpack{bez123} and \Lpack{multiply} packages\thanks{This +% file has version number \fileversion, last revised +% \filedate.}} +% +% \author{% +% Peter Wilson\\ +% Catholic University of America\thanks{This work was originally +% performed as +% a Guest Researcher at the National Institute of Standards and Technology.} \\ +% Now at \texttt{peter.r.wilson@boeing.com} +% } +% \date{\filedate} +% \maketitle +% \begin{abstract} +% The \Lpack{bez123} package provides for the drawing of linear, cubic, +% and rational quadratic Bezier curves. The \Lpack{multiply} package +% provides a command to multiply a length without numerical overflow. +% \end{abstract} +% \tableofcontents +% \listoftables +% \listoffigures +% +% \StopEventually{} +% +% +% +% \section{Introduction} +% +% This document provides the commented source for a \LaTeX{} +% package file that extends the \LaTeX{} facilities for drawing +% Bezier curves. The package was originally developed as part of +% a suite designed for the typesetting of +% documents according to the rules for ISO international +% standards~\cite{PRW96i}. +% This manual is typeset according to the conventions of the +% \LaTeX{} \textsc{docstrip} utility which enables the automatic +% extraction of the \LaTeX{} macro source files~\cite{GOOSSENS94}. +% +% Drawing a non-rational quadratic Bezier curve is provided as part +% of the standard \LaTeX{} system. +% Section~\ref{sec:usage} provides the user manual for the new commands +% supplied by this package for drawing a variety of Bezier curves. +% These include commands for drawing linear and cubic non-rational Bezier +% curves and rational quadratic curves. +% +% Section~\ref{sec:bez} describes the implementation of the package. +% As a side-effect of the implementation, a facility is also provided +% for performing multiplication in \TeX{} without overflow. This is +% described in Section~\ref{sec:mnoflow}. +% +% +% +% \section{Usage} \label{sec:usage} +% +% Leslie Lamport provided the means of drawing a quadratic Bezier curve +% \emph{via} the \LaTeXe{} |\qbezier|~\cite[pp. 125--126]{LAMPORT94} command. +% This package +% extends the Bezier facility by providing commands to draw linear, +% rational quadratic, and cubic Bezier curves. +% +% Bezier curves are named after Pierre Bezier who invented them. They +% are widely used within Computer Aided Design (CAD) programs and other +% graphics systems; descriptions can be found in many places, with varying +% degrees of mathematical complexity, such +% as~\cite{FandP,MORTENSON85,FARIN90}. +% +% The Bezier curve is a parameterized curve of degree $n$ and can +% therefore be specified by $(n+1)$ points +% (i.e., point $p_{0}$ through $p_{n}$). +% Among its other properties, a Bezier curve of degree $n$ passes through +% through the points $p_{0}$ and $p_{n}$ and passes close to the other +% defining points. The general equation for a Bezier curve of degree $n$ with +% parameter $t$ is +% \begin{equation} +% p(t) = a_{0} + a_{1}t + a_{2}t^{2} + \cdots + a_{n}t^{n} \label{eq:gen} +% \end{equation} +% where the coefficients $a_{i}$ depend on the defining points, and +% traditionally $0 \leq t \leq 1$. +% +% For a linear (degree $1$) curve, the equation is +% \begin{equation} +% p(t) = p_{0} + (p_{1} - p_{0})t \label{eq:lin} +% \end{equation} +% By inspection, $p(0) = p_{0}$ and $p(1) = p_{1}$. +% +% Rearranging \eqref{eq:gen} slightly we get +% \begin{equation} +% p(t) - p_{0} = (p_{1} - p_{0})t \label{eq:lin2} +% \end{equation} +% In other words, we can march along the curve from the starting point to +% the ending point by evaluating the right hand side of +% \eqref{eq:lin2} for increasing values of the parameter $t$. +% +% In order to shorten the equations slightly, and also make them more +% convenient to work with numerically, we will use the notation +% \begin{displaymath} +% l_{pq} = p_{p} - p_{q} +% \end{displaymath} +% Thus, the final form for the linear Bezier curve is +% \begin{equation} +% p(t) - p_{0} = l_{10}t \label{eq:lin3} +% \end{equation} +% +% \DescribeMacro{\lbezier} +% The command |\lbezier[|\meta{N}|](|\meta{p0}|)(|\meta{p1}|)| draws a +% linear Bezier curve with \meta{N} plotted points from the point \meta{p0} +% (with coordinates \meta{x0,y0}) to the point \meta{p1} (with +% coordinates \meta{x1,y1}). \meta{N} is an optional argument. If it is +% either not given or is given with a value of zero, +% then the command will calculate the number of points to be +% plotted, subject to a maximum number. +% There must be no spaces between the arguments to the +% |\lbezier| command; this restriction also applies to the other Bezier +% drawing commands provided by the \Lpack{bez123} package. +% +% Figure~\ref{fig:beta} shows an example of a dotted line drawn using +% the |\lbezier| command. The actual code used is: +% \begin{verbatim} +% \lbezier[50](15,30)(30,0) +% \end{verbatim} +% thus drawing a straight line consisting of 50 points. +% +% \DescribeMacro{\qbeziermax} +% The standard \LaTeX{} command |\qbeziermax| sets a maximum limit +% on the number of points used to draw any of the Bezier curves. +% +% \DescribeMacro{\thinlines} +% \DescribeMacro{\thicklines} +% \DescribeMacro{\linethickness} +% The `points' used in drawing the Bezier curves are small squares. The +% size of these squares are controlled by the standard \LaTeX{} +% |\thinlines|, |\thicklines| and/or |\linethickness| commands. +% Consult Lamport~\cite{LAMPORT94} for descriptions of these, and +% |\qbeziermax|, commands. +% +% +% It is convenient to introduce some general properties of Bezier curves +% at this point. +% \begin{itemize} +% \item A degree $n$ Bezier curve is defined by $(n+1)$ points which we +% will label as $p_{0}$ through $p_{n}$. The lines joining the points +% $p_{0}, p_{1}, \ldots , p_{n}$ are called the \emph{control polygon}. +% The Bezier curve is parameterized by a variable we will call $t$, with +% $0 \leq t \leq 1$. +% \item A degree $n$ Bezier curve starts at point $p_{0}$ and ends at +% point $p_{n}$. +% \item At $t=0$ the curve passes through $p_{0}$ and is tangent to the +% line $l_{10} = p_{1}-p_{0}$. +% \item At $t=1$ the curve passes through $p_{n}$ and is tangent to the +% line $l_{(n)(n-1)} = p_{n}-p_{(n-1)}$. +% \item A \emph{non-rational} Bezier curve lies within the \emph{convex +% hull}\footnote{The convex hull can be thought of as the shape that a rubber +% band will take if it is stretched around pins placed at each point.} +% of the points $p_{0}$ through $p_{n}$. For examples of convex hulls see +% figure~\ref{fig:ch}. Note that the shape of a convex hull is independant +% of the ordering of the points. +% \end{itemize} +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(70,80) +% ^^A degree 3 +% \put(0,5){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0}} +% \put(10,30){\circle{2}} +% \put(8,30){\makebox(0,0)[br]{1}} +% \put(20,0){\circle{2}} +% \put(22,0){\makebox(0,0)[bl]{2}} +% \put(30,30){\circle{2}} +% \put(32,30){\makebox(0,0)[bl]{3}} +% ^^A convex hull +% \put(0,0){\line(1,0){20}} +% \put(20,0){\line(1,3){10}} +% \put(30,30){\line(-1,0){20}} +% \put(10,30){\line(-1,-3){10}} +% ^^A control polygon +% ^^A \put(0,0){\vector(1,3){10}} +% ^^A \put(10,30){\vector(1,-3){10}} +% ^^A \put(20,0){\vector(1,3){10}} +% \thicklines +% ^^A \cbezier[30](0,0)(10,30)(20,0)(30,30) +% \thinlines +% \end{picture}} +% ^^A degree 3 +% \put(0,45){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0, 3}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{1}} +% \put(0,30){\circle{2}} +% \put(2,30){\makebox(0,0)[bl]{2}} +% ^^A convex hull +% \put(0,0){\line(1,0){30}} +% \put(30,0){\line(-1,1){30}} +% \put(0,30){\line(0,-1){30}} +% ^^A control polygon +% ^^A \put(0,0){\vector(1,0){30}} +% ^^A \put(30,0){\vector(-1,1){30}} +% ^^A \put(0,30){\vector(0,-1){30}} +% \thicklines +% ^^A \cbezier[30](0,0)(30,0)(0,30)(0,0) +% \thinlines +% \end{picture}} +% ^^A degree 3 +% \put(45,0){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0}} +% \put(10,30){\circle{2}} +% \put(8,30){\makebox(0,0)[br]{2}} +% \put(20,0){\circle{2}} +% \put(22,0){\makebox(0,0)[bl]{3}} +% \put(30,30){\circle{2}} +% \put(32,30){\makebox(0,0)[bl]{1}} +% ^^A convex hull +% \put(0,0){\line(1,0){20}} +% \put(20,0){\line(1,3){10}} +% \put(30,30){\line(-1,0){20}} +% \put(10,30){\line(-1,-3){10}} +% ^^A control polygon +% ^^A \put(0,0){\vector(1,1){30}} +% ^^A \put(30,30){\vector(-1,0){20}} +% ^^A \put(10,30){\vector(1,-3){10}} +% \thicklines +% ^^A \cbezier(0,0)(30,30)(10,30)(20,0) +% \thinlines +% \end{picture}} +% \put(45,45){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{1}} +% \put(0,30){\circle{2}} +% \put(2,30){\makebox(0,0)[bl]{2}} +% \put(10,10){\circle{2}} +% \put(8,10){\makebox(0,0)[br]{3}} +% ^^A convex hull +% \put(0,0){\line(1,0){30}} +% \put(30,0){\line(-1,1){30}} +% \put(0,30){\line(0,-1){30}} +% ^^A control polygon +% ^^A \put(0,0){\vector(1,0){30}} +% ^^A \put(30,0){\vector(-1,1){30}} +% ^^A \put(0,30){\vector(1,-2){10}} +% \thicklines +% ^^A \cbezier(0,0)(30,0)(0,30)(10,10) +% \thinlines +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{Four sets of points and their convex hulls} \label{fig:ch} +% \end{figure} +% +% The equation for cubic Bezier curves is +% \begin{equation} +% p(t) - p_{0} = 3l_{10}t + 3(l_{21} - l_{10})t^{2} + (l_{30} - 3l_{21})t^{3} +% \label{eq:cubic} +% \end{equation} +% +% \DescribeMacro{\cbezier} +% The command +% |\cbezier[|\meta{N}|](|\meta{p0}|)(|\meta{p1}|)(|\meta{p2}|)(|\meta{p3}|)| +% draws a cubic Bezier curve, as defined by \eqref{eq:cubic}, +% from point \meta{p0} to point \meta{p3}, where \meta{p1} and \meta{p2} +% are the intermediate points defining the control polygon. +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(70,80) +% ^^A degree 3 +% \put(0,5){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0}} +% \put(10,30){\circle{2}} +% \put(8,30){\makebox(0,0)[br]{1}} +% \put(20,0){\circle{2}} +% \put(22,0){\makebox(0,0)[bl]{2}} +% \put(30,30){\circle{2}} +% \put(32,30){\makebox(0,0)[bl]{3}} +% ^^A convex hull +% ^^A \put(0,0){\line(1,0){20}} +% ^^A \put(20,0){\line(1,3){10}} +% ^^A \put(30,30){\line(-1,0){20}} +% ^^A \put(10,30){\line(-1,-3){10}} +% ^^A control polygon +% \put(0,0){\vector(1,3){10}} +% \put(10,30){\vector(1,-3){10}} +% \put(20,0){\vector(1,3){10}} +% \thicklines +% \cbezier[30](0,0)(10,30)(20,0)(30,30) +% \thinlines +% \end{picture}} +% ^^A degree 3 +% \put(0,45){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0, 3}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{1}} +% \put(0,30){\circle{2}} +% \put(2,30){\makebox(0,0)[bl]{2}} +% ^^A convex hull +% ^^A \put(0,0){\line(1,0){30}} +% ^^A \put(30,0){\line(-1,1){30}} +% ^^A \put(0,30){\line(0,-1){30}} +% ^^A control polygon +% \put(0,0){\vector(1,0){30}} +% \put(30,0){\vector(-1,1){30}} +% \put(0,30){\vector(0,-1){30}} +% \thicklines +% \cbezier[30](0,0)(30,0)(0,30)(0,0) +% \thinlines +% \end{picture}} +% ^^A degree 3 +% \put(45,0){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0}} +% \put(10,30){\circle{2}} +% \put(8,30){\makebox(0,0)[br]{2}} +% \put(20,0){\circle{2}} +% \put(22,0){\makebox(0,0)[bl]{3}} +% \put(30,30){\circle{2}} +% \put(32,30){\makebox(0,0)[bl]{1}} +% ^^A convex hull +% ^^A \put(0,0){\line(1,0){20}} +% ^^A \put(20,0){\line(1,3){10}} +% ^^A \put(30,30){\line(-1,0){20}} +% ^^A \put(10,30){\line(-1,-3){10}} +% ^^A control polygon +% \put(0,0){\vector(1,1){30}} +% \put(30,30){\vector(-1,0){20}} +% \put(10,30){\vector(1,-3){10}} +% \thicklines +% \cbezier(0,0)(30,30)(10,30)(20,0) +% \thinlines +% \end{picture}} +% \put(45,45){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{1}} +% \put(0,30){\circle{2}} +% \put(2,30){\makebox(0,0)[bl]{2}} +% \put(10,10){\circle{2}} +% \put(8,10){\makebox(0,0)[br]{3}} +% ^^A convex hull +% ^^A \put(0,0){\line(1,0){30}} +% ^^A \put(30,0){\line(-1,1){30}} +% ^^A \put(0,30){\line(0,-1){30}} +% ^^A control polygon +% \put(0,0){\vector(1,0){30}} +% \put(30,0){\vector(-1,1){30}} +% \put(0,30){\vector(1,-2){10}} +% \thicklines +% \cbezier(0,0)(30,0)(0,30)(10,10) +% \thinlines +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{Four sets of points, the cubic Bezier curves and their control +% polygons. Left --- curves plotted with $N=30$; Right --- +% curves plotted with $N=0$} \label{fig:cp} +% \end{figure} +% +% Figure~\ref{fig:cp} shows four such cubic Bezier curves, their +% defining points and their control polygons. These are the same points +% that were used in figure~\ref{fig:ch} to illustrate convex hulls. It is +% easy to verify that a cubic Bezier curve does indeed lie within the convex +% hull of its defining points. The curves on the left of the figure were +% specified with a value of 30 for the argument \meta{N}, while those +% on the right had no value given for \meta{N} and thus were drawn with +% the number of plotted points calculated by the drawing algorithm. +% The actual drawing commands used were: +% \begin{verbatim} +% \cbezier[30](0,0)(10,30)(20,0)(30,30) +% \cbezier[30](0,0)(30,0)(0,30)(0,0) +% \cbezier(0,0)(30,30)(10,30)(20,0) +% \cbezier(0,0)(30,0)(0,30)(10,10) +% \end{verbatim} +% Note that points are plotted along the curve at equidistant values of the +% of the parameter $t$. However, as the relationship between the actual +% distance in $(x,y)$ coordinate space is a non-linear function of $t$, +% the seperation between the plotted points is non-uniform. +% +% The equation for a \emph{non-rational} quadratic Bezier curve is +% \begin{equation} +% p(t) - p_{0} = 2l_{10}t + (l_{20} - 2l_{10})t^{2} \label{eq:quad} +% \end{equation} +% Using standard \LaTeX{} this can be drawn by the |\qbezier| command. +% There is another form of a quadratic Bezier curve called a \emph{rational} +% quadratic Bezier curve. Its equation is +% \begin{equation} +% p(t) - p_{0} = \frac^^A +% {2w_{1}l_{10}t + (w_{2}l_{20} - 2w_{1}l_{10})t^{2}}^^A +% {w_{0} + 2\omega_{10}t + (\omega_{20} - \omega_{10})t^{2}} +% \label{eq:rqfull} +% \end{equation} +% where the $w_{i}$ are the \emph{weights} corresponding to the +% points $p_{i}$ and $\omega_{pq} = w_{p} - w_{q}$. The shape of a +% non-rational curve can be changed by changing the positions of the defining +% points. The shape of a rational curve can also be modified by changing +% the values of the weights. A rational curve +% has the same general properties, outlined above, as a non-rational curve +% with the exception that the curve may lie outside the convex hull of the +% control polygon. +% +% For the purposes at hand, we use a more restricted form of a +% rational quadratic Bezier curve, obtained by putting +% $W = w_{1}/w_{0}$ and then making +% $w_{0} = w_{2} = 1$ in \eqref{eq:rqfull}. Performing these +% substitutions we end up with +% \begin{equation} +% p(t) - p_{0} = \frac^^A +% {2Wl_{10}t + (l_{20} - 2Wl_{10})t^{2}}^^A +% {1 + 2(1 - W)t + 2(1 - W)t^{2}} +% \label{eq:rqfinal} +% \end{equation} +% Note that when $W=1$, (\ref{eq:rqfinal}) reduces to \eqref{eq:quad} +% and when $W=0$ it effectively reduces to \eqref{eq:lin3}. +% +% It turns out that a non-rational quadratic Bezier curve is an arc of +% a parabola, which is one of the conic curves. All the other conic curves +% can be represented by the rational quadratic Bezier curve described +% by \eqref{eq:rqfinal} by suitable choices for the value of $W$. +% From now on, we will call $W$ the \emph{weight} of the rational quadratic +% Bezier curve. Table~\ref{tab:rq} lists the value, or value range, +% of $W$ for the various forms of the conic curve.\footnote{We do not deal +% with the degenerate cases.} For the case of a circle, $\beta$ is the +% angle between the lines $l_{10} = (p_{1} - p_{0})$ and +% $l_{20} = (p_{2} - p_{0})$, as shown in figure~\ref{fig:beta}. +% +% \begin{table} +% \centering +% \caption{Conic forms of the rational quadratic Bezier curve} \label{tab:rq} +% \begin{tabular}{lc} \hline +% Conic form & Weight ($W$) \\ \hline +% Hyperbola & $\|W\| > 1$ \\ +% Parabola & $\|W\| = 1$ \\ +% Ellipse & $0 < \|W\| < 1$ \\ +% Circle & $\|l_{10}\| = \|l_{21}\|$ and $W = \cos \beta$ \\ +% Straight line & $W = 0$ \\ \hline +% \end{tabular} +% \end{table} +% +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(30,40) +% \put(0,5){\begin{picture}(30,30) +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,30){\circle{2}} +% \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \thicklines +% \put(15,30){\vector(-1,-2){15}} +% \put(0,0){\vector(1,0){30}} +% ^^A dashed line from 0 to 2 +% ^^A \lbezier(15,30)(30,0) +% \lbezier[50](15,30)(30,0) +% \thinlines +% \put(15,26){\makebox(0,0){$\beta$}} +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{The angle $\beta$} \label{fig:beta} +% \end{figure} +% +% \DescribeMacro{\rqbezier} +% The command +% |\rqbezier[|\meta{N}|](|\meta{p0}|)(|\meta{p1}|)(|\meta{p2}|)(|\meta{W}|)| +% draws a rational quadratic Bezier curve from \meta{p0} to \meta{p2} with +% weight \meta{W}, according to \eqref{eq:rqfinal}. As in the +% other Bezier commands, \meta{N} is optional and controls the number +% of plotted points along the curve. Figure~\ref{fig:qrb} shows several +% rational quadratic curves, all with the same control polygon but with +% differing values for the weight $W$. The code is: +% \begin{verbatim} +% \rqbezier[100](15,30)(0,0)(30,0)(4) +% \rqbezier[100](15,30)(0,0)(30,0)(2) +% \rqbezier(15,30)(0,0)(30,0)(1) +% \rqbezier[100](15,30)(0,0)(30,0)(0.75) +% \rqbezier[100](15,30)(0,0)(30,0)(0.5) +% \rqbezier[100](15,30)(0,0)(30,0)(0.25) +% \rqbezier(15,30)(0,0)(30,0)(0) +% \end{verbatim} +% When $W > 1$ the curve is pulled toward the point $p_{1}$. Conversely, +% when $W < 1$ the curve is pushed away from the point $p_{1}$. In all +% cases, though, the curve starts and stops at $p_{0}$ and $p_{2}$ +% respectively. +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(30,40) +% \put(0,5){\begin{picture}(30,30) +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,30){\circle{2}} +% \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \thinlines +% \put(15,30){\vector(-1,-2){15}} +% \put(0,0){\vector(1,0){30}} +% ^^A dashed line from 0 to 2 +% ^^A \lbezier(15,30)(30,0) +% ^^A \lbezier[50](15,30)(30,0) +% ^^A \thinlines +% ^^A \put(15,26){\makebox(0,0){$\beta$}} +% \thicklines +% \rqbezier[100](15,30)(0,0)(30,0)(4) +% \rqbezier[100](15,30)(0,0)(30,0)(2) +% \rqbezier(15,30)(0,0)(30,0)(1) +% \rqbezier[100](15,30)(0,0)(30,0)(0.75) +% \rqbezier[100](15,30)(0,0)(30,0)(0.5) +% \rqbezier[100](15,30)(0,0)(30,0)(0.25) +% \rqbezier(15,30)(0,0)(30,0)(0) +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{The effect of weight variation ($W \geq 0$) +% on rational quadratic Bezier curves +% (\texttt{weightscale = \theweightscale} (the default)) } +% \label{fig:qrb} +% \end{figure} +% +% Like the case of the cubic curve, points are plotted at equidistant +% values of the parameter $t$. The relationship between parameter value +% and coordinate positions in the rational case are highly non-linear. +% Thus the distance between the plotted points can vary quite remarkably. +% This is an inherent disadvantage with this type of curve. The user's remedy +% is to increase the number of points to be plotted, but this can lead to +% \TeX{} running out of memory, not to mention the increased time to +% generate the drawing. +% +% \DescribeMacro{\setweightscale} +% \DescribeMacro{\resetweightscale} +% Because of the way in which \TeX{} performs arithmetic, and especially +% division, it +% is necessary to perform some scaling operations on the divisor when +% evaluating \eqref{eq:rqfinal}. The optimum value for the +% scaling is a complex function of the weight and the size and orientation +% of the control polygon. The algorithm uses a heuristic approach to +% calculate a `good' value but is not always successful. The +% |\setweightscale{|\meta{number}|}| command can be used to specify +% a scale factor. \meta{number} must be a positive integer. The +% |\resetweightscale| command resets the scale factor to its default +% value, which is currently 10000 (ten thousand). +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(70,80) +% \put(0,5){\begin{picture}(30,30) +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,30){\circle{2}} +% \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \thinlines +% ^^A \put(15,30){\vector(-1,-2){15}} +% ^^A \put(0,0){\vector(1,0){30}} +% ^^A dashed line from 0 to 2 +% ^^A \lbezier(15,30)(30,0) +% ^^A \lbezier[50](15,30)(30,0) +% ^^A \thinlines +% ^^A \put(15,26){\makebox(0,0){$\beta$}} +% \thicklines +% \setweightscale{100} +% \rqbezier[100](15,30)(0,0)(30,0)(4) +% \rqbezier[100](15,30)(0,0)(30,0)(2) +% \rqbezier(15,30)(0,0)(30,0)(1) +% \rqbezier[100](15,30)(0,0)(30,0)(0.75) +% \rqbezier[100](15,30)(0,0)(30,0)(0.5) +% \rqbezier[100](15,30)(0,0)(30,0)(0.25) +% \rqbezier(15,30)(0,0)(30,0)(0) +% \put(15,-5){\makebox(0,0)[b]{\texttt{weightscale = \theweightscale}}} +% \end{picture}} +% \put(0,45){\begin{picture}(30,30) +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,30){\circle{2}} +% \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \thinlines +% ^^A \put(15,30){\vector(-1,-2){15}} +% ^^A \put(0,0){\vector(1,0){30}} +% ^^A dashed line from 0 to 2 +% ^^A \lbezier(15,30)(30,0) +% ^^A \lbezier[50](15,30)(30,0) +% ^^A \thinlines +% ^^A \put(15,26){\makebox(0,0){$\beta$}} +% \thicklines +% \setweightscale{1000} +% \rqbezier[100](15,30)(0,0)(30,0)(4) +% \rqbezier[100](15,30)(0,0)(30,0)(2) +% \rqbezier(15,30)(0,0)(30,0)(1) +% \rqbezier[100](15,30)(0,0)(30,0)(0.75) +% \rqbezier[100](15,30)(0,0)(30,0)(0.5) +% \rqbezier[100](15,30)(0,0)(30,0)(0.25) +% \rqbezier(15,30)(0,0)(30,0)(0) +% \put(15,-5){\makebox(0,0)[b]{\texttt{weightscale = \theweightscale}}} +% \end{picture}} +% \put(45,5){\begin{picture}(30,30) +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,30){\circle{2}} +% \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \thinlines +% ^^A \put(15,30){\vector(-1,-2){15}} +% ^^A \put(0,0){\vector(1,0){30}} +% ^^A dashed line from 0 to 2 +% ^^A \lbezier(15,30)(30,0) +% ^^A \lbezier[50](15,30)(30,0) +% ^^A \thinlines +% ^^A \put(15,26){\makebox(0,0){$\beta$}} +% \thicklines +% \resetweightscale +% \rqbezier[100](15,30)(0,0)(30,0)(4) +% \rqbezier[100](15,30)(0,0)(30,0)(2) +% \rqbezier(15,30)(0,0)(30,0)(1) +% \rqbezier[100](15,30)(0,0)(30,0)(0.75) +% \rqbezier[100](15,30)(0,0)(30,0)(0.5) +% \rqbezier[100](15,30)(0,0)(30,0)(0.25) +% \rqbezier(15,30)(0,0)(30,0)(0) +% \put(15,-5){\makebox(0,0)[b]{\texttt{weightscale = \theweightscale}}} +% \end{picture}} +% \put(45,45){\begin{picture}(30,30) +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,30){\circle{2}} +% \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \thinlines +% ^^A \put(15,30){\vector(-1,-2){15}} +% ^^A \put(0,0){\vector(1,0){30}} +% ^^A dashed line from 0 to 2 +% ^^A \lbezier(15,30)(30,0) +% ^^A \lbezier[50](15,30)(30,0) +% ^^A \thinlines +% ^^A \put(15,26){\makebox(0,0){$\beta$}} +% \thicklines +% \setweightscale{100000} +% \rqbezier[100](15,30)(0,0)(30,0)(4) +% \rqbezier[100](15,30)(0,0)(30,0)(2) +% \rqbezier(15,30)(0,0)(30,0)(1) +% \rqbezier[100](15,30)(0,0)(30,0)(0.75) +% \rqbezier[100](15,30)(0,0)(30,0)(0.5) +% \rqbezier[100](15,30)(0,0)(30,0)(0.25) +% \rqbezier(15,30)(0,0)(30,0)(0) +% \put(15,-5){\makebox(0,0)[b]{\texttt{weightscale = \theweightscale}}} +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \resetweightscale +% \caption{The effect of \texttt{weightscale} on the drawing +% of rational quadratic Bezier curves} +% \label{fig:qrw} +% \end{figure} +% +% Figure~\ref{fig:qrw} illustrates the effect on changing the +% \texttt{weightscale} used for drawing the same curves as shown +% in figure~\ref{fig:qrb}. Note that the \texttt{weightscale} +% has no effect when +% $W = 1$ or $W = 0$ as in these cases the curves are drawn using the +% algorithms for the |\qbezier| and |\lbezier| commands respectively. +% +% It is obvious that some choices give very poorly formed curves. In +% other cases the curves may be poorly formed but do result in interesting +% cross-stitch like patterns. +% +% Table~\ref{tab:rq} indicates that it is possible to draw circular +% arcs using a rational quadratic Bezier curves. The two legs of the +% control polygon define the tangents to the curve at the +% end points. +% Therefore, to draw a circular arc the two legs must be equal in length. +% That is, the convex hull is an isosceles triangle. In the special case +% when the convex hull forms an equilateral triangle, the required +% weight ($\cos \beta$, see figure~\ref{fig:beta}) for drawing a circular +% arc is $\cos \beta = 0.5$. Further, +% for any given control polygon the the curves drawn with weights of +% $\pm W$ are complementary. That is, the curve with weight $-W$ is +% the `remainder' of the curve drawn with weight $W$. Thus, we have a +% simple means of drawing a complete circle, as shown in figure~\ref{fig:qrc}. +% The plotting commands of interest were: +% \begin{verbatim} +% \lbezier[25](0,0)(15,26) +% \lbezier[25](0,0)(30,0) +% \setweightscale{50000} +% \rqbezier[100](15,26)(0,0)(30,0)(0.5) +% \rqbezier[200](15,26)(0,0)(30,0)(-0.5) +% \resetweightscale +% \end{verbatim} +% where the |\lbezier| drawing commands were used to draw the dotted outline +% of the control polygon. +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \setweightscale{50000} +% \begin{picture}(60,62) +% \put(0,5){\begin{picture}(30,30) +% \thinlines +% \put(0,0){\circle{2}} +% \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,26){\circle{2}} +% \put(13,26){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% \put(32,0){\makebox(0,0)[bl]{2}} +% ^^A polygon +% \lbezier[25](0,0)(15,26) +% \lbezier[25](0,0)(30,0) +% ^^A RQBEZIER +% \thicklines +% \rqbezier[100](15,26)(0,0)(30,0)(0.5) +% \rqbezier[200](15,26)(0,0)(30,0)(-0.5) +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{Rational quadratics with weights of $\pm 0.5$ and an equilateral +% triangular convex hull +% (\texttt{weightscale = \theweightscale}) } \label{fig:qrc} +% \resetweightscale +% \end{figure} +% +% A more robust picture of the same circle is shown in +% figure~\ref{fig:qr3c} where the complete circle is pieced together from +% three non-complementary circular arcs. The drawing commands of interest +% were +% \begin{verbatim} +% \rqbezier[100](15,26)(0,0)(30,0)(0.5) +% \rqbezier[100](30,0)(60,0)(45,26)(0.5) +% \rqbezier[100](45,26)(30,52)(15,26)(0.5) +% \end{verbatim} +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(60,62) +% \put(0,5){\begin{picture}(60,52) +% \thinlines +% \put(0,0){\circle{2}} +% ^^A \put(-2,0){\makebox(0,0)[br]{1}} +% \put(15,26){\circle{2}} +% ^^A \put(13,30){\makebox(0,0)[br]{0}} +% \put(30,0){\circle{2}} +% ^^A \put(32,0){\makebox(0,0)[bl]{2}} +% \put(60,0){\circle{2}} +% \put(45,26){\circle{2}} +% \put(30,52){\circle{2}} +% ^^A polygon +% \lbezier[50](0,0)(30,52) +% \lbezier[50](30,52)(60,0) +% \lbezier[50](0,0)(60,0) +% ^^A RQBEZIER +% \thicklines +% \rqbezier[100](15,26)(0,0)(30,0)(0.5) +% \rqbezier[100](30,0)(60,0)(45,26)(0.5) +% \rqbezier[100](45,26)(30,52)(15,26)(0.5) +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{Three rational quadratics with weights of $0.5$ +% (\texttt{weightscale = \theweightscale}) } +% \label{fig:qr3c} +% \end{figure} +% +% The astute reader will have realised that the divisor in +% \eqref{eq:rqfinal} can go to zero, and can even be negative. +% This has interesting consequences, both when trying to do computer +% arithmetic, and also on the the kind of curve that results. Essentially, +% the curve tends to $\infty$ as $W \rightarrow +0$. At $W = -0$ the curve +% is at $-\infty$ and then it tends to $-0$ as $W \rightarrow -\infty$. +% We will get a curve point at $\infty$ whenever $W = -1$ and a `negative' +% curve for $W < -1$. +% +% \begin{figure} +% \centering +% \setlength{\unitlength}{1mm} +% \begin{picture}(60,60) +% \put(30,20){\begin{picture}(30,20) +% \thinlines +% \put(0,10){\circle{2}} +% \put(30,0){\circle{2}} +% \put(30,20){\circle{2}} +% ^^A polygon +% \lbezier[25](30,20)(0,10) +% \lbezier[25](0,10)(30,0) +% ^^A RQBEZIER +% \thicklines +% \rqbezier[100](30,20)(0,10)(30,0)(2) +% \rqbezier[100](30,20)(0,10)(30,0)(-2) +% \end{picture}} +% \end{picture} +% \setlength{\unitlength}{1pt} +% \caption{A rational quadratic that has gone negative; weights of $\pm 2$ +% (\texttt{weightscale = \theweightscale}) } +% \label{fig:neg} +% \end{figure} +% +% This effect is shown in figure~\ref{fig:neg} which draws the two branches +% of a hyperbola. The basic code for the illustration was +% \begin{verbatim} +% \lbezier[25](30,20)(0,10) +% \lbezier[25](0,10)(30,0) +% \rqbezier[100](30,20)(0,10)(30,0)(2) +% \rqbezier[100](30,20)(0,10)(30,0)(-2) +% \end{verbatim} +% where the control polygon was drawn using the |\lbezier| commands. +% +% +% \section{The \Lpack{bez123} package implementation} \label{sec:bez} +% +% \LaTeX{} provides a facility for drawing quadratic Bezier curves. +% This package provides additional facilities for drawing linear, +% rational quadratic, and cubic Bezier curves. +% +% +% Announce the name and version of the package, which requires \LaTeXe. +% \begin{macrocode} +%<*bez> +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{bez123}[1998/10/14 v1.1 Bezier curves] +% \end{macrocode} +% \changes{v1.1}{1998/10/14}{Added call to include multiply package} +% The package also requires the \Lpack{multiply} package. +% \begin{macrocode} +\RequirePackage{multiply}[1998/10/14] +%</bez> +% \end{macrocode} +% +% +% \subsection{Arithmetic in \TeX} +% +% All arithmetic in \TeX{} is based on integer arithmetic, with a +% maximum integer value of $M = \number\maxdimen$. For example, +% \setcounter{weightscale}{8}\makeatletter\divide\c@weightscale by 3\makeatother +% $8/3 = \theweightscale$, +% \setcounter{weightscale}{9}\makeatletter\divide\c@weightscale by 3\makeatother +% $9/3 = \theweightscale$, and +% \setcounter{weightscale}{10}\makeatletter\divide\c@weightscale by 3\makeatother +% $10/3 = \theweightscale$. +% In other words, division always reduces the absolute value of the dividend, +% and also possibly truncates the value. One consequence of this is that the +% ordering of multiplication and division is important. For instance, +% \setcounter{weightscale}{8}\makeatletter\multiply\c@weightscale by 3 \divide\c@weightscale by 3\makeatother +% $(8 \times 3)/3 = \theweightscale$ but +% \setcounter{weightscale}{8}\makeatletter\divide\c@weightscale by 3 \multiply\c@weightscale by 3\makeatother +% $(8/3) \times 3 = \theweightscale$! +% Thus, in arithmetic calculations involving both multiplication and +% division, the dividend should be maximised and the divisor minimised, +% with multiplication preceeding division; also remembering that there +% is a limit on the size of an integer. To avoid multiplication overflow +% when calculating say, $a \times b$, we must ensure that +% $\|a\| \leq \|M/b\|$. +% +% When calculating polynomials, such as that in \eqref{eq:gen}, +% we use a technique called Horner's schema, which is also known as nested +% multiplication. A general cubic equation, for example, can be written as: +% \begin{equation} +% p(t) - a_{0} = t(a_{1} + t(a_{2} + ta_{3})) \label{eq:horn} +% \end{equation} +% The following pseudo-code shows one way to implement Horner's schema for +% plotting $N$ points in the interval $0 \leq t \leq 1$ +% of \eqref{eq:horn} using integer arithmetic. +% \begin{verbatim} +% procedure plot_cubic(a0, a1, a2, a3:vector; N:integer); +% local p:vector; end_local; +% a3 := a3/N; +% repeat i := 0 to N by 1; +% p := a3*i; +% p := p + a2; p := p/N; p := p*i; +% p := p + a1; p := p/N; p := p*i; +% draw(p + a0); +% end_repeat; +% return; +% end_procedure; +% \end{verbatim} +% We use the above algorithm, with suitable modifications according to the +% degree of the polynomial, for plotting the points along Bezier curves. +% +% \subsection{Linear Bezier curves} +% +% \begin{macrocode} +%<*bez> +% \end{macrocode} +% +% As a linear curve is simpler than a quadratic curve there is no +% need to declare extra variables from those used in the kernel by the +% |\qbezier| macro. +% +% \begin{macro}{\lbezier} +% The user command to draw a linear Bezier curve represented by +% \eqref{eq:lin3}. The form of the command is:\\ +% |\lbezier[|\meta{N}|]{(|\meta{p0}|)(|\meta{p1}|)| \\ +% where \meta{pN} is the comma seperated X and Y coordinate values of +% point \textit{pN}. +% +% \begin{macrocode} +\newcommand{\lbezier}[2][0]{\@lbez{#1}#2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@lbez} +% The drawing macro. +% \begin{macrocode} +\gdef\@lbez#1(#2,#3)(#4,#5){% +%%%%\def\lbezier#1(#2,#3)(#4,#5){% + \ifnum #1<\@ne +% \end{macrocode} +% When the number of plotting points are not given, then we calculate +% how many are needed. First determine the X distance between the end points. +% \begin{macrocode} + \@ovxx = #4\unitlength + \advance\@ovxx by -#2\unitlength + \ifdim \@ovxx < \z@ + \@ovxx = -\@ovxx + \fi +% \end{macrocode} +% Similarly calculate the Y distance. +% \begin{macrocode} + \@ovyy = #5\unitlength + \advance\@ovyy by -#3\unitlength + \ifdim \@ovyy < \z@ + \@ovyy = -\@ovyy + \fi +% \end{macrocode} +% Temporarily store the maximum distance in |\@multicnt|. +% \begin{macrocode} + \ifdim \@ovxx > \@ovyy + \@multicnt = \@ovxx + \else + \@multicnt = \@ovyy + \fi +% \end{macrocode} +% We use a small square as the visual representation of a point. +% Calculate the number of points required to give 50\% overlap of adjacent +% squares, making +% sure that it doesn't exceed the limit. Store the result in |\@multicnt|. +% \begin{macrocode} + \@ovxx = 0.5\@halfwidth + \divide\@multicnt by \@ovxx + \ifnum \qbeziermax < \@multicnt + \@multicnt = \qbeziermax\relax + \fi + \else +% \end{macrocode} +% The number of points is given. +% \begin{macrocode} + \@multicnt = #1\relax + \fi +% \end{macrocode} +% +% Now we can prepare the constants for the plotting loop. +% \begin{macrocode} + \@tempcnta = \@multicnt + \advance\@tempcnta by \@ne + \@ovdx = #4\unitlength + \advance\@ovdx by -#2\unitlength + \divide\@ovdx by \@multicnt + \@ovdy = #5\unitlength + \advance\@ovdy by -#3\unitlength + \divide\@ovdy by \@multicnt +% \end{macrocode} +% The next bit of code defines the size of the square representing a point. +% \begin{macrocode} + \setbox\@tempboxa\hbox{\vrule \@height\@halfwidth + \@depth \@halfwidth + \@width \@wholewidth}% +% \end{macrocode} +% Start the plot at the first point. +% \begin{macrocode} + \put(#2,#3){% + \count@ = \z@ + \@whilenum{\count@ < \@tempcnta}\do +% \end{macrocode} +% Evaluate the polynomial (simple in this case) using Horner's schema. +% \begin{macrocode} + {\@xdim = \count@\@ovdx + \@ydim = \count@\@ovdy +% \end{macrocode} +% Plot this point. +% \begin{macrocode} + \raise \@ydim + \hb@xt@\z@{\kern\@xdim + \unhcopy\@tempboxa\hss}% + \advance\count@\@ne}}% +% \end{macrocode} +% The end of the definition of |\@lbez|. +% \begin{macrocode} +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Cubic Bezier curves} +% +% As cubic curves are more complex than quadratic curves we need some +% extra variables. +% \begin{macro}{\@wxc} +% \begin{macro}{\@wyc} +% Lengths. +% \begin{macrocode} +\newlength{\@wxc} +\newlength{\@wyc} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\cbezier} +% The user command for drawing a cubic Bezier curve as represented +% by \eqref{eq:cubic}. It is called as: \\ +% |\cbezier[|\meta{N}|](|\meta{p0}|)(|\meta{p1}|)(|\meta{p2}|)(|\meta{p3}|)|. +% +% \begin{macrocode} +\newcommand{\cbezier}[2][0]{\@cbez{#1}#2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@cbez} +% The drawing macro for cubic Bezier curves. +% \begin{macrocode} +\gdef\@cbez#1(#2,#3)(#4,#5)(#6,#7)(#8,#9){% + \ifnum #1<\@ne +% \end{macrocode} +% We have to calculate the number of plotting points required. We will +% use the maximum of the box enclosing the convex hull as a measure. +% First do the X value, using |\@ovxx| to store the maximum X coordinate +% and |\@ovdx| the minimum. +% \begin{macrocode} + \@ovxx = #2\unitlength + \@ovdx = \@ovxx + \@ovdy = #4\unitlength + \ifdim \@ovdy > \@ovxx + \@ovxx = \@ovdy + \fi + \ifdim \@ovdy < \@ovdx + \@ovdx = \@ovdy + \fi + \@ovdy = #6\unitlength + \ifdim \@ovdy > \@ovxx + \@ovxx = \@ovdy + \fi + \ifdim \@ovdy < \@ovdx + \@ovdx = \@ovdy + \fi + \@ovdy = #8\unitlength + \ifdim \@ovdy > \@ovxx + \@ovxx = \@ovdy + \fi + \ifdim \@ovdy < \@ovdx + \@ovdx = \@ovdy + \fi +% \end{macrocode} +% Store the maximum X in |\@ovxx|. +% \begin{macrocode} + \advance\@ovxx by -\@ovdx +% \end{macrocode} +% Repeat the process for the maximum Y value, finally storing +% this in |\@ovyy|. +% \begin{macrocode} + \@ovyy = #3\unitlength + \@ovdy = \@ovyy + \@ovdx = #5\unitlength + \ifdim \@ovdx > \@ovyy + \@ovyy = \@ovdx + \fi + \ifdim \@ovdx < \@ovdy + \@ovdy = \@ovdx + \fi + \@ovdx = #7\unitlength + \ifdim \@ovdx > \@ovyy + \@ovyy = \@ovdx + \fi + \ifdim \@ovdx < \@ovdy + \@ovdy = \@ovdx + \fi + \@ovdx = #9\unitlength + \ifdim \@ovdx > \@ovyy + \@ovyy = \@ovdx + \fi + \ifdim \@ovdx < \@ovdy + \@ovdy = \@ovdx + \fi + \advance\@ovyy by -\@ovdy +% \end{macrocode} +% Temporarily store the max of X and Y in |\@multicnt|. +% \begin{macrocode} + \ifdim \@ovxx > \@ovyy + \@multicnt = \@ovxx + \else + \@multicnt = \@ovyy + \fi +% \end{macrocode} +% Calculate the number of points required to give 50\% overlap, making +% sure that it doesn't exceed the limit. Store the number of points in +% |\@multicnt|. +% \begin{macrocode} + \@ovxx = 0.5\@halfwidth + \divide\@multicnt by \@ovxx + \ifnum \qbeziermax < \@multicnt + \@multicnt = \qbeziermax\relax + \fi + \else +% \end{macrocode} +% The number of points is given. +% \begin{macrocode} + \@multicnt = #1\relax + \fi +% \end{macrocode} +% +% Now we can prepare the constants for the plotting loop. First the control +% counts. +% \begin{macrocode} + \@tempcnta = \@multicnt + \advance\@tempcnta by \@ne +% \end{macrocode} +% Then the cubic coefficients, firstly for X. +% \begin{macrocode} + \@ovdx = #4\unitlength \advance\@ovdx by -#2\unitlength + \@ovxx = #6\unitlength \advance\@ovxx by -\@ovdx + \multiply\@ovdx by \thr@@ + \advance\@ovxx by -#4\unitlength \multiply\@ovxx by \thr@@ + \@wxc = #4\unitlength \advance\@wxc by -#6\unitlength + \multiply\@wxc by \thr@@ \advance\@wxc by #8\unitlength + \advance\@wxc by -#2\unitlength \divide\@wxc by \@multicnt +% \end{macrocode} +% And similarly for Y. +% \begin{macrocode} + \@ovdy = #5\unitlength \advance\@ovdy by -#3\unitlength + \@ovyy = #7\unitlength \advance\@ovyy by -\@ovdy + \multiply\@ovdy by \thr@@ + \advance\@ovyy by -#5\unitlength \multiply\@ovyy by \thr@@ + \@wyc = #5\unitlength \advance\@wyc by -#7\unitlength + \multiply\@wyc by \thr@@ \advance\@wyc by #9\unitlength + \advance\@wyc by -#3\unitlength \divide\@wyc by \@multicnt +% \end{macrocode} +% Set up the plotting box. +% \begin{macrocode} + \setbox\@tempboxa\hbox{\vrule \@height\@halfwidth + \@depth \@halfwidth + \@width \@wholewidth}% +% \end{macrocode} +% Start the plot at the first point. +% \begin{macrocode} + \put(#2,#3){% + \count@ = \z@ + \@whilenum{\count@ < \@tempcnta}\do + {\@xdim = \count@\@wxc + \advance\@xdim by \@ovxx + \divide\@xdim by \@multicnt + \multiply\@xdim by \count@ + \advance\@xdim by \@ovdx + \divide\@xdim by \@multicnt + \multiply\@xdim by \count@ + \@ydim = \count@\@wyc + \advance\@ydim by \@ovyy + \divide\@ydim by \@multicnt + \multiply\@ydim by \count@ + \advance\@ydim by \@ovdy + \divide\@ydim by \@multicnt + \multiply\@ydim by \count@ +% \end{macrocode} +% Plot the point. +% \begin{macrocode} + \raise \@ydim + \hb@xt@\z@{\kern\@xdim + \unhcopy\@tempboxa\hss}% + \advance\count@\@ne}}% +% \end{macrocode} +% The end of the definition of |\@cbez|. +% \begin{macrocode} +} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Quadratic rational Bezier curve} +% +% This is the most complex of the Bezier curves that we deal with. +% We need yet more variables. +% +% \begin{macro}{\@ww} +% \begin{macro}{\@wwa} +% \begin{macro}{\@wwb} +% \begin{macro}{\@wwo} +% \begin{macro}{\@wwi} +% Variables for the weight calculations. +% \begin{macrocode} +\newlength{\@ww} +\newlength{\@wwa} +\newlength{\@wwb} +\newlength{\@wwo} +\newlength{\@wwi} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\c@@pntscale} +% Scale factor for points. +% \begin{macrocode} +\newcounter{@pntscale} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\c@weightscale} +% Scale factor for divisor. +% \begin{macrocode} +\newcounter{weightscale} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\botscale} +% Scale factor for bottom weights. +% \begin{macrocode} +\newlength{\botscale} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\setweightscale} +% User level command |\setweightscale{|\meta{number}|}| for setting the +% divisor scaling. +% \begin{macrocode} +\newcommand{\setweightscale}[1]{\setcounter{weightscale}{#1}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\resetweightscale} +% User level command for setting the divisor scaling to its default +% value ($10^{4}$). We also ensure that the scaling is set to this value. +% \begin{macrocode} +\newcommand{\resetweightscale}{\setcounter{weightscale}{10000}} +\resetweightscale +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\rqbezier} +% The user level command for drawing a rational quadratic Bezier curve +% as represented by \eqref{eq:rqfinal}. The form of the command is \\ +% |\rqbezier[|\meta{N}|](|\meta{p0}|)(|\meta{p1}|)(|\meta{p2}|)(|\meta{W}|)| \\ +% where the arguments are as per the other Bezier drawing commands, but with +% the final argument being the weight. +% +% \begin{macrocode} +\newcommand{\rqbezier}[2][0]{\@rqbez{#1}#2} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@rqbez} +% The drawing macro for a rational quadratic Bezier curve. If the weight +% is such that the curve is either rational quadratic ($W = 1$) or +% linear ($W = 0$), we use the simpler drawing macro. +% \begin{macrocode} +\gdef\@rqbez#1(#2,#3)(#4,#5)(#6,#7)(#8){% + \@ovxx = #8\unitlength + \ifdim\@ovxx = \unitlength + \PackageWarning{bez123}{Rational quadratic denerates to quadratic} + \qbezier[#1](#2,#3)(#4,#5)(#6,#7) + \else + \ifdim\@ovxx = \z@ + \PackageWarning{bez123}{Rational quadratic degenerates to linear} + \lbezier[#1](#2,#3)(#6,#7) + \else +% \end{macrocode} +% Calculate the maximum length of the control polygon's bounding box. +% Store the result in |\@wwi|. +% \begin{macrocode} + \@ovxx = #4\unitlength + \advance\@ovxx by -#2\unitlength + \ifdim \@ovxx < \z@ + \@ovxx = -\@ovxx + \fi + \@ovdx = #6\unitlength + \advance\@ovdx by -#4\unitlength + \ifdim \@ovdx < \z@ + \@ovdx = -\@ovdx + \fi + \ifdim \@ovxx < \@ovdx + \@ovxx = \@ovdx + \fi + \@ovyy = #5\unitlength + \advance\@ovyy by -#3\unitlength + \ifdim \@ovyy < \z@ + \@ovyy = -\@ovyy + \fi + \@ovdy = #7\unitlength + \advance\@ovdy by -#5\unitlength + \ifdim \@ovdy < \z@ + \@ovdy = -\@ovdy + \fi + \ifdim \@ovyy < \@ovdy + \@ovyy = \@ovdy + \fi + \ifdim \@ovxx > \@ovyy + \@multicnt = \@ovxx + \else + \@multicnt = \@ovyy + \fi + \@wwi = \@multicnt sp +% \end{macrocode} +% Now determine the number of points to be plotted. +% \begin{macrocode} + \ifnum #1<\@ne + \@ovxx = 0.5\@halfwidth + \divide\@multicnt by \@ovxx + \ifnum\qbeziermax < \@multicnt + \@multicnt = \qbeziermax\relax + \fi + \else +% \end{macrocode} +% Number of points is a given. +% \begin{macrocode} + \@multicnt = #1\relax + \fi +% \end{macrocode} +% We are going to plot the curve in two halves in an attempt to reduce +% roundoff problems. At +% a minimum this should at least make a symmetrical curve look symmetric +% about its mid point. +% \begin{macrocode} + \@tempcnta = \@multicnt + \advance\@tempcnta by \@ne + \divide\@tempcnta by \tw@ + \advance\@tempcnta by \@ne +% \end{macrocode} +% We now have to deal with a possible multiplication overflow problem due +% to multiplication by the weight. In \eqref{eq:rqfinal} the potentially +% largest term is the coefficient of $t^{2}$ (i.e., $(l_{20}-2Wl_{10})$). +% The maximum length likely to be encountered is, say, 10 inches for a +% drawing on either A4 or US letterpaper. This is approximately +% $4.8\times10^{8}$sp. Doing a little arithmetic, and remembering that the +% maximum length in \TeX{} is $M = \number\maxdimen$sp, it means that we must +% have $\|W\| \leq 1$ to prevent overflow. However, a typical range for +% $W$ is $-10 \leq W \leq 10$. Therefore we might have to do some scaling. +% Being pessimistic, we'll assume that $l_{20} = - l_{10}$ and that $l_{10}$ +% is the largest dimension in the drawing. To prevent overflow we then have to +% meet the condition $\|W\| \leq (M - l_{20})/2l_{20}$, where all lengths are +% positive. We will use |\c@@pntscale| as a scale factor on $W$ to meet this +% condition. Earlier we set |\@wwi| to be the positive value of the largest +% dimension in the drawing. +% +% Set the distance scale factor. First evaluating the test condition. +% \begin{macrocode} + \@wwo = \maxdimen + \advance\@wwo by -\@wwi + \divide\@wwo by \tw@ + \divide\@wwo by \@wwi +% \end{macrocode} +% Now perform the check and set the scale factor. We have to get a positive +% integer value for $W$ as it may be a fraction. Actually, we only need to +% be concerned if $\|W\| > 1$. +% \begin{macrocode} + \@wwi = 10sp + \@wwi = #8\@wwi + \ifdim\@wwi < \z@ + \@wwi = -\@wwi + \fi + \divide\@wwi by 10\relax + \ifdim\@wwi < \@wwo + \c@@pntscale = \@ne + \else + \divide\@wwi by \tw@ + \ifdim\@wwi < \@wwo + \c@@pntscale = \tw@ + \else + \divide\@wwi by \tw@ + \ifdim\@wwi < \@wwo + \c@@pntscale = 4\relax + \else + \divide\@wwi by \tw@ + \ifdim\@wwi < \@wwo + \c@@pntscale = 8\relax + \else + \c@@pntscale = 16\relax + \fi + \fi + \fi + \fi +% \end{macrocode} +% Calculate the constants for the top line of the function. +% \begin{macrocode} + \@ovxx = #4\unitlength \advance\@ovxx by -#2\unitlength + \multiply\@ovxx by \tw@ + \divide\@ovxx by \c@@pntscale + \@ovdx = #8\@ovxx + \@ovxx = #6\unitlength \advance\@ovxx by -#2\unitlength + \divide\@ovxx by \c@@pntscale + \advance\@ovxx by -\@ovdx + \divide\@ovxx by \@multicnt + \@ovyy = #5\unitlength \advance\@ovyy by -#3\unitlength + \multiply\@ovyy by \tw@ + \divide\@ovyy by \c@@pntscale + \@ovdy = #8\@ovyy + \@ovyy = #7\unitlength \advance\@ovyy by -#3\unitlength + \divide\@ovyy by \c@@pntscale + \advance\@ovyy by -\@ovdy + \divide\@ovyy by \@multicnt +% \end{macrocode} +% Now the constants for the bottom line. We also need to do some scaling +% here. This scaling can be set by the user. +% \begin{macrocode} + \setlength{\botscale}{\c@weightscale sp} + \@wwo = \botscale + \@wwi = #8\@wwo + \@wwa = \@wwo \advance\@wwa by -\@wwi + \multiply\@wwa by \tw@ + \@wwb = \@wwa + \divide\@wwb by \@multicnt +% \end{macrocode} +% Prepare for the drawing. +% \begin{macrocode} + \@wwi = \botscale + \setbox\@tempboxa\hbox{\vrule \@height\@halfwidth + \@depth \@halfwidth + \@width \@wholewidth}% +% \end{macrocode} +% Draw the first half of the curve. +% \begin{macrocode} + \put(#2,#3){% + \count@ = \z@ + \@whilenum{\count@ < \@tempcnta}\do + {\@xdim = \count@\@ovxx + \advance\@xdim by \@ovdx + \divide\@xdim by \@multicnt + \multiply\@xdim by \count@ + \@ydim = \count@\@ovyy + \advance\@ydim by \@ovdy + \divide\@ydim by \@multicnt + \multiply\@ydim by \count@ + \@ww = \count@\@wwb + \advance\@ww by -\@wwa + \divide\@ww by \@multicnt + \multiply\@ww by \count@ + \advance\@ww by \@wwo + \divide\@ww by \c@@pntscale + \ifdim\@ww = \z@ +% \end{macrocode} +% We are about to divide by |\@ww| which is zero. Treat |\@ww| as unity. +% \begin{macrocode} + \else + \divide\@xdim by \@ww + \divide\@ydim by \@ww + \fi +% \end{macrocode} +% For reasons I don't understand, the \% signs at the end of the next few +% lines are important! +% \begin{macrocode} + \multnooverflow{\@xdim}{\botscale}% + \multnooverflow{\@ydim}{\botscale}% + \raise \@ydim + \hb@xt@\z@{\kern\@xdim + \unhcopy\@tempboxa\hss}% + \advance\count@\@ne}} +% \end{macrocode} +% +% We now repeat the above process for plotting the second half of the +% curve, starting at the end point. +% +% Calculate the constants for the top line of the function. +% \begin{macrocode} + \@ovxx = #4\unitlength \advance\@ovxx by -#6\unitlength + \multiply\@ovxx by \tw@ + \divide\@ovxx by \c@@pntscale + \@ovdx = #8\@ovxx + \@ovxx = #2\unitlength \advance\@ovxx by -#6\unitlength + \divide\@ovxx by \c@@pntscale + \advance\@ovxx by -\@ovdx + \divide\@ovxx by \@multicnt + \@ovyy = #5\unitlength \advance\@ovyy by -#7\unitlength + \multiply\@ovyy by \tw@ + \divide\@ovyy by \c@@pntscale + \@ovdy = #8\@ovyy + \@ovyy = #3\unitlength \advance\@ovyy by -#7\unitlength + \divide\@ovyy by \c@@pntscale + \advance\@ovyy by -\@ovdy + \divide\@ovyy by \@multicnt +% \end{macrocode} +% The constants for the bottom line are the same as before as the function +% is symmetric. Similarly we don't need to recalculate the size of the +% rule box. +% +% Draw the second half of the curve. +% \begin{macrocode} + \put(#6,#7){% + \count@ = \z@ + \@whilenum{\count@ < \@tempcnta}\do + {\@xdim = \count@\@ovxx + \advance\@xdim by \@ovdx + \divide\@xdim by \@multicnt + \multiply\@xdim by \count@ + \@ydim = \count@\@ovyy + \advance\@ydim by \@ovdy + \divide\@ydim by \@multicnt + \multiply\@ydim by \count@ + \@ww = \count@\@wwb + \advance\@ww by -\@wwa + \divide\@ww by \@multicnt + \multiply\@ww by \count@ + \advance\@ww by \@wwo + \divide\@ww by \c@@pntscale + \ifnum\@ww = \z@ +% \end{macrocode} +% We are about to divide by |\@ww| which is zero. Treat |\@ww| as unity. +% \begin{macrocode} + \else + \divide\@xdim by \@ww + \divide\@ydim by \@ww + \fi +% \end{macrocode} +% For reasons I don't understand, the \% signs at the end of the next few +% lines are important! +% \begin{macrocode} + \multnooverflow{\@xdim}{\botscale}% + \multnooverflow{\@ydim}{\botscale}% + \raise \@ydim + \hb@xt@\z@{\kern\@xdim + \unhcopy\@tempboxa\hss}% + \advance\count@\@ne}} +% End of definition of |\@rqbez|. +% \begin{macrocode} + \fi\fi} +% \end{macrocode} +% \end{macro} +% +% The end of this package. +% \begin{macrocode} +%</bez> +% \end{macrocode} +% +% \section{Multiplication without overflow: The \Lpack{multiply} package} \label{sec:mnoflow} +% +% \TeX{} provides for integer arithmetic, subject to an upper limit +% given by |\maxdim|. For at least the \Lpack{bez123} package we need to +% be able to multiply without overflow. +% +% Announce the name of the package. +% \changes{v1.1}{1998/10/14}{Put multnooverflow into a seperate package} +% \begin{macrocode} +%<*mult> +\ProvidesPackage{multiply}[1998/10/14 v1.1 Multiplication of lengths without overflow] +% \end{macrocode} +% +% \begin{macro}{\n@fl@wa} +% \begin{macro}{\n@fl@wb} +% \begin{macro}{\n@fl@wc} +% \begin{macro}{\ifch@nge} +% We need three length variables for this function. +% We also need a boolean flag for dealing with negative numbers. +% \begin{macrocode} +\newlength{\n@fl@wa} +\newlength{\n@fl@wb} +\newlength{\n@fl@wc} +\newif\ifch@nge +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\multnooverflow} +% +% The routine |\multnooverflow{|\meta{a}|}{|\meta{b}|}| sets +% $a$ to the minimum of $ab$ and |\maxdimen|, preserving signs. \meta{a} +% must be a length; it must not be a number literal. +% +% \begin{macrocode} +\newcommand{\multnooverflow}[2]{% + \n@fl@wa = #1\relax% + \n@fl@wb = #2\relax% + \ch@ngefalse% +% \end{macrocode} +% Easy if $-1 \leq b \leq 1$. +% \begin{macrocode} + \ifnum\n@fl@wb = \@ne% + \else% + \ifnum\n@fl@wb = \z@% + \n@fl@wa = \z@% + \else% + \ifnum\n@fl@wb = \m@ne% + \ch@ngetrue% + \else% +% \end{macrocode} +% Also easy if $-1 \leq a \leq 1$. +% \begin{macrocode} + \ifnum\n@fl@wa = \z@% + \else% + \ifnum\n@fl@wa = \@ne% + \n@fl@wa = \n@fl@wb% + \else% + \ifnum\n@fl@wa = \m@ne% + \n@fl@wa = -\n@fl@wb% + \else% +% \end{macrocode} +% We have to check for potential overflow. First make sure that we deal +% only with positive values. +% \begin{macrocode} + \ifnum\n@fl@wa < \z@% + \ch@ngetrue% + \n@fl@wa = -\n@fl@wa% + \fi% + \ifnum\n@fl@wb < \z@% + \n@fl@wb = -\n@fl@wb% + \ifch@nge% + \ch@ngefalse% + \else% + \ch@ngetrue% + \fi% + \fi% +% \end{macrocode} +% Check for overflow. +% \begin{macrocode} + \n@fl@wc = \maxdimen% + \divide\n@fl@wc by \n@fl@wb% + \advance\n@fl@wc by -1sp% \m@ne + \ifnum\n@fl@wa > \n@fl@wc% +% \end{macrocode} +% We have overflow. Set the multiplication result to |\maxdimen|. +% \begin{macrocode} + \n@fl@wa = \maxdimen% + \PackageWarning{multiply}{Multiplication overflow}% + \else% +% \end{macrocode} +% It is safe to do the multiplication. +% \begin{macrocode} + \multiply\n@fl@wa by \n@fl@wb% + \fi% + \fi% + \fi% + \fi% + \fi% + \fi% + \fi% +% \end{macrocode} +% The result of $ab$ is in |\n@fl@wa|. Adjust the sign if necessary. +% \begin{macrocode} + \ifch@nge% + \n@fl@wa = -\n@fl@wa% + \fi% +% \end{macrocode} +% Return the result in the first argument variable. +% \begin{macrocode} + #1 = \n@fl@wa% +} +% \end{macrocode} +% \end{macro} +% +% +% The end of this package. +% \begin{macrocode} +%</mult> +% \end{macrocode} +% +% +% \bibliographystyle{alpha} +% +% \begin{thebibliography}{GMS94} +% +% \bibitem[Far90]{FARIN90} +% Gerald Farin. +% \newblock {\em Curves and Surfaces for Computer Aided Geometric Design --- A +% Practical Guide}. +% \newblock Academic Press, Inc., second edition, 1990. +% +% \bibitem[FP81]{FandP} +% I.~D. Faux and M.~J. Pratt. +% \newblock {\em Computational Geometry for Design and Manufacture}. +% \newblock Ellis Horwood, 1981. +% +% \bibitem[GMS94]{GOOSSENS94} +% Michel Goossens, Frank Mittelbach, and Alexander Samarin. +% \newblock {\em The LaTeX Companion}. +% \newblock Addison-Wesley Publishing Company, 1994. +% +% \bibitem[Lam94]{LAMPORT94} +% Leslie Lamport. +% \newblock {\em LaTeX: A Document Preparation System}. +% \newblock Addison-Wesley Publishing Company, second edition, 1994. +% +% \bibitem[Mor85]{MORTENSON85} +% Michael~E. Mortenson. +% \newblock {\em Geometric Modeling}. +% \newblock John Wiley \& Sons, Inc., 1985. +% +% \bibitem[Wil96]{PRW96i} +% Peter~R. Wilson. +% \newblock {\em {LaTeX for standards: The LaTeX package files user manual}}. +% \newblock NIST Report NISTIR, June 1996. +% +% \end{thebibliography} +% +% +% \Finale +% \PrintIndex +% +\endinput + +%% \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 \~} + + |