% \iffalse meta comment % % Copyright (c) Gerhard A. Bachmaier 2001-2005 % % This program can be redistributed and/or modified under the terms % of the LaTeX Project Public License Distributed from CTAN % archives in directory macros/latex/base/ as file lppl.txt; either % version 1 of the License, or (at your option) any later version. % % Gerhard A. Bachmaier % Institute for Medical Informatics, Statistics, and Documentation % Medical University of Graz % send bugs to: gerhard.bachmaier@meduni-graz.at % % \fi % % \iffalse % %<*driver> \ProvidesFile{ebezier.drv} % %\ProvidesPackage{ebezier} [2005/03/01 v4] % %<*driver> \documentclass{article} \usepackage{ebezier} \usepackage{calc} \usepackage{doc} \EnableCrossrefs \CodelineIndex %\DisableCrossrefs \begin{document} \DocInput{ebezier.dtx} \end{document} % % \fi % % \CheckSum{1955} % % \DoNotIndex{\@X,\@Xa,\@Xb,\@Xc,\@Y,\@Ya,\@Yb,\@Yc} % \DoNotIndex{\@Z,\@Za,\@Zb,\@Zc,\@Zd,\@Ze,\@Zf,\@Zg,\@Zh,\@Zi,\@Zj} % \DoNotIndex{\@clnht,\@clnwd,\@dashdim,\@ifnextchar,\@killglue,\@ne} % \DoNotIndex{\@ovdx,\@ovdy,\@ovri,\@ovro,\@ovxx,\@ovyy} % \DoNotIndex{\@tempdima,\@tempdimb,\@tempdimc,\@tfor,\@und@fined} % \DoNotIndex{\@whilenum,\@xdim,\@ydim,\advance,\approx,\bullet} % \DoNotIndex{\c@@cnta,\c@@cntb,\c@@cntc,\c@@cntd,\chardef,\copy} % \DoNotIndex{\csname,\def,\dimen,\divide,\do,\dp,\else,\endcsname,\fi} % \DoNotIndex{\gdef,\hb@xt@,\hbox,\hskip,\hss,\ht,\ifdim,\ifnum,\ifx} % \DoNotIndex{\ignorespaces,\kern,\let,\long,\loop,\lower,\Lpack} % \DoNotIndex{\magstep,\magstephalf} % \DoNotIndex{\multiply,\myname,\NeedsTeXFormat,\newcommand,\newcounter} % \DoNotIndex{\newfont,\newif,\newlength,\newsavebox,\oval,\pi,\put} % \DoNotIndex{\raise,\ratio,\realname,\relax,\repeat,\RequirePackage} % \DoNotIndex{\reserved@a,\setbox,\setcounter,\setlength,\space,\sqrt} % \DoNotIndex{\the,\thr@@,\tw@,\unhcopy,\unitlength,\value,\vrule,\wd,\z@} % % \title{Using ebezier} % \author{Gerhard A. Bachmaier} % \date{March 1, 2005} % % \renewcommand{\topfraction}{.6} % \renewcommand{\bottomfraction}{.6} % \setcounter{totalnumber}{5} % \renewcommand{\textfraction}{.1} % \setlength{\unitlength}{1pt} % \setlength{\parskip}{3pt} % \font \logo=logo10 scaled \magstep1 % \newcommand{\formstrut}{\rule{0mm}{2mm}} % \providecommand{\Metafont}{% % {\logo META}\discretionary{}{-}{}{\logo FONT}} % \renewcommand{\thefootnote}{\fnsymbol{footnote}} % \renewcommand{\arraystretch}{1.2} % \newcommand\SB[2]{\setbox1=\hbox{#1#2}} % \newcommand*{\Lpack}[1]{\textsf {#1}} % % \maketitle % % \begin{abstract} % The package \Lpack{ebezier} is an extension of the (old) % \Lpack{bezier.sty} which is now part of \LaTeXe. It defines % linear and cubic Bernste\u\i{}n polynomials together with some % plotting macros for arcs. % % With the aid of the \Lpack{calc} package also the calculation of % square roots and henceforward lengths is supplied. % \end{abstract} % % % \StopEventually{} % % \section*{Preamble} % % If you want to draw complicated and/or lots of pictures, you should use % \textsc{PostScript} for generating your plots and \Lpack{dvips} to include % them in \TeX\ documents. \textsc{PostScript} can plot lines with arbitrary % slope and unlimited length and circles with arbitrary radius just by using % one command. See also the \LaTeX\ Graphics Companion\cite{T1} for further % possibilities. There is also a new package \Lpack{pict2e}\cite{pict2e} a\-vail\-able % which is preferrable for PDF and \textsc{PostScript}. % % This package will support also lines with arbitrary slopes and unlimited % length, but each line has to be generated as a sample of points. Each % point reduces \TeX's memory and you will very likely have to overcome some % \texttt{TeX capacity excxeeded...} messages. % % Exact circles would involve trigonometric functions or square roots % to be evaluated by \TeX. % Even with some tricks for reducing the effort of the calculation algorithm % there would be hundreds of calculations for each point.\footnote{% % To use \TeX\ for complex computations is as satisfactory as using your desk % calculator for writing tasks. But if you really want to do it e.g.\ the digits 7353 % can be read (rotating by $180^0$) as % \texttt{ESEL}, the german word for ``donkey''.} % But they may be quite % well approximated by cubic bezier curves, also supplied in this package % (The quality of interpolation is discussed in some detail in the Section % \textit{Fitting Arcs}.) In fact, the small circles in the \LaTeX-\texttt{lcircle} fonts % are also generated by the same method. % % For draft papers use all kind of bezier curves with small number of points, % just for the final run increase the numbers. \TeX\ memory can be set free % again with {\verb+\clearpage+} at the end of complicated pictures. It's % also a good idea to have them at an extra page (option \verb+[p]+ for % \texttt{figure} environments). % % For optical constructions the software LaTeXPiX\cite{PiX} may be a starting point. % This software supports cubic bezier curves defined in this package or from % \Lpack{bez123}\cite{T5}. % % \section{Mathematical Definitions} % % A Bernste\u\i{}n polynomial of degree $n-1\: (n\ge 2)$ is defined by % $n$ points $z_1, z_2,\ldots,z_n$ % % \[ \mathcal{B}_{n-1} [t] = \sum_{i=0}^{n-1} {n-1\choose i} % (1-t)^{n-1-i} t^i z_{i+1}\quad t\in[0,1].\footnotemark\]% % \footnotetext{There are also % variants of this definitions with all coefficients $\equiv 1$.} % % The points $z_i, \: i\in\lbrace1,\ldots,n\rbrace$, may be considered as % real numbers, then $\mathcal{B}$ is really a polynomial in $t$. Or they % denote points in a plane, which notation we will use further. In this case % both \emph{components} are polynominials and the graph for $\mathcal{B}$ % is---part of---an algebraic curve. % % \bigskip % % All these graphs have in common: % \begin{itemize} % \item The graph is contained in the convex hull of the defining points. % \item The graph starts at $z_1$ and stops at $z_n$. % \item At the endpoints the tangents coincident with % the directions $z_1-z_2$ and $z_{n-1}-z_n$ correspondingly. % \end{itemize} % % For $n=2$ the Bernste\u\i{}n polynomial $\mathcal{B}_1$ reduces to the % linear form spanned by $z_1$ and $z_2$. The parametrization in $t$ % % \[ \mathcal{B}_1 [t] =(1-t) z_1 + t z_2=: t[z_1,z_2]\] % % is also known as \emph{convex coordinates} for the segment % $\overline{\formstrut z_1z_2}$. % % \begin{figure}[htb] % \begin{center} % \begin{picture}(100,60) % \put(-25,-10){\framebox(155,70){}} % \put(20,10){\line(2,1){60}} % \put(20,10){\makebox(0,0){$\bullet$}} % \put(80,40){\makebox(0,0){$\bullet$}} % \put(40,20){\makebox(0,0){$\bullet$}} % \put(-17,15){$z_1 (t=0)$} % \put(75,47){$z_2 (t=1)$} % \put(40,10){$t=1/3$} % \end{picture} % \end{center} % \caption{Line defined by two points} % \end{figure} % % \bigskip % % For $n=3$ the result is a (quadratic) parabola which can also % be constructed as the convex hull of all tangents in the % triangle $\Delta\,z_1 z_2 z_3$ (examplified in Fig.\ 2b). % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(250,120) % \put(-15,-10){\framebox(280,130){}} % \Qbezier[300](0,0)(50,100)(100,0) % \put(0,0){\makebox(0,0){$\bullet$}} % \put(100,0){\makebox(0,0){$\bullet$}} % \put(50,100){\makebox(0,0){$\bullet$}} % \put(-6,10){$z_1$} % \put(50,105){$z_2$} % \put(99,10){$z_3$} % \put(0,0){\line(1,2){50}} % \put(100,0){\line(-1,2){50}} %% % \put(150,0){\makebox(0,0){$\bullet$}} % \put(250,0){\makebox(0,0){$\bullet$}} % \put(200,100){\makebox(0,0){$\bullet$}} % \put(144,10){$z_1$} % \put(200,105){$z_2$} % \put(249,10){$z_3$} % \put(150,0){\line(1,2){50}} % \put(250,0){\line(-1,2){50}} % \lbezier[50](160,20)(210,80) % \lbezier[30](170,40)(220,60) % \lbezier[30](180,60)(230,40) % \lbezier[50](190,80)(240,20) % \lbezier[50](155,10)(205,90) % \lbezier[50](165,30)(215,70) % \lbezier[30](175,50)(225,50) % \lbezier[50](185,70)(235,30) % \lbezier[50](195,90)(245,10) % \end{picture} % \end{center} % \caption{Quadratic parabola (a) as Bernste\u\i{}n polynom of degree 2 % and (b) as hull of tangents} % \end{figure} % % For $n=4$ finally we arrive at the cubic curves used e.g.\ in the \Metafont\ % book\cite{T3}. % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(100,100) % \put(-10,-10){\framebox(130,110){}} % \Cbezier[500](0,0)(10,80)(70,40)(100,0) % \put(5,0){$z_1$} % \put(10,85){$z_2$} % \put(70,50){$z_3$} % \put(105,0){$z_4$} % \end{picture} % \end{center} % \caption{A simple cubic parabola.} % \end{figure} % % % We will not use more complicated polynomials for several reasons: % % \begin{itemize} % \item Higher degree polynomials require more operations to calculate % just one point of the graph. % \item For sketches (and \textbf{not} exact graphs!) cubic splines are % sufficient to scope with all kind of different curvature requirements. % \item \TeX\ can handle integers up to $2^{28}$, and ``real number'' lengths % are transformed to integers (multiples of scaled points: 1\,pt=$2^{16}$ sp) \cite{T2}. To stay % within this restricted range even for cubic beziers we have to do calculations % in the right order. Changing the order of multiplication and divisions will % result very soon in arithmetic overflows. Also multiplication with these pseudo-real % numbers is not an associative operation (due to the range limits!). % \item The maximum number of arguments for commands in \TeX\ is limited to nine, % which is just enough for four points and a number. % \end{itemize} % % % % % \section{The Plotting Macros} % % \subsection{Simple Beziers} % % There are two first level plot commands to be used in a % \LaTeXe\ \texttt{picture} environment: % % \begin{verbatim} % \lbezier[n](x1,y1)(x2,y2) % \cbezier[n](x1,y1)(x2,y2)(x3,y3)(x4,y4) % \end{verbatim} % % The arguments in square brackets are optional! If they are omitted or $n=0$ an adequate number % will be calculated (cf. Section 8). % % \DescribeMacro{\qbezier} % \verb+\lbezier+ draws line segments from point $(x_1,y_1)$ % to $(x_2,y_2)$, or more exactly, $n+1$ intermediate points, while % \verb+\cbezier+ is an implementation of the cubic variant. Just for % completeness let me remind you that the quadratic % variant---\verb+\qbezier[n](x1,y1)(x2,y2)(x3,y3)+---is part of \LaTeXe. % % \DescribeMacro{\qbeziermax} % $n$ is always limited by the number \verb+\qbeziermax+ (=500). % % You may change \verb+\qbeziermax+ by a command like (it is not a counter!) % \verb+\renewcommand{\qbeziermax}{1000}+. % % \subsubsection{lbezier} % \DescribeMacro{\lbezier} % \verb+\lbezier+ is straightforward defined as % linear polynomial. It produces equally spaced points. % % \begin{verbatim} % ... % \put(0,25){\line(1,0){90}} % \lbezier[20](0,10)(90,10) % \lbezier[200](0,-5)(90,-5) % ... % \end{verbatim} % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(150,30) % \put(-20,-15){\framebox(230,50){}} % \put(0,25){\line(1,0){90}} % \put(95,25){\makebox(100,0){\protect\LaTeXe\ \protect\texttt{line}}} % \lbezier[20](0,10)(90,10) % \put(95,10){\makebox(100,0){\protect\texttt{lbezier} (21 points)}} % \lbezier[200](0,-5)(90,-5) % \put(95,-5){\makebox(100,-5){\protect\texttt{lbezier} (201 points)}} % \end{picture} % \end{center} % \caption{Different line commands} % \end{figure} % % Use \verb+\lbezier+ only in cases where the line you want to plot is not within % the scope of the \verb+\line+ command, i.e. the slope is not a small rational number % and/or the length is too small. % % \subsubsection{cbezier} % % \DescribeMacro{\cbezier} % Just like the \verb+\lbezier+ macro \verb+\cbezier+ uses no tricks to generate % the third order polynomial. The examples are from the \Metafont\ book % (pp. 13)\cite{T3}, where the influence of changing the order of the % controlling points ($z_1$ up to $z_4$) is also demonstrated. % % \begin{verbatim} % ... % % z1=(0,16) z2=(40,84) z3=(136,96) z4=(250,0) % % z12=(20,50) z23=(88,90) z34=(193,48) z123=(54,70) % % z234=(140.5,69) % \cbezier[400](0,16)(40,84)(136,96)(250,0) % \lbezier[30](0,16)(40,84) % \lbezier[30](40,84)(136,96) % \lbezier[30](136,96)(250,0) % \lbezier[30](20,50)(88,90) % \lbezier[30](88,90)(193,48) % \lbezier[30](54,70)(140.5,69) % ... % \end{verbatim} % \begin{figure}[hbt] % \begin{center} % \begin{picture}(250,100) % \put(-10,-10){\framebox(270,115){}} % \cbezier[400](0,16)(40,84)(136,96)(250,0) % \lbezier[30](0,16)(40,84) % \lbezier[30](40,84)(136,96) % \lbezier[30](136,96)(250,0) % \lbezier[30](20,50)(88,90) % \lbezier[30](88,90)(193,48) % \lbezier[30](54,70)(140.5,69) % \end{picture} % \end{center} % \caption{Iteration scheme for one point} % \end{figure} % % % \DescribeMacro{\Cbezier} % The variant \verb+\Cbezier+ draws also dots and lines for the controlling points (see % Fig.\ 6)\footnote{It resets also the plot symbol to the standard one; cf. Section 7}. % % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(184,100) % \put(-10,-10){\framebox(204,100){}} % \Cbezier[200](0,50)(12,72)(43,78)(84,50) % \Cbezier[200](100,50)(143,78)(112,72)(184,50) % \Cbezier[200](12,22)(0,0)(43,28)(84,0) % \Cbezier[200](100,0)(184,0)(112,22)(143,28) % \end{picture} % \end{center} % \caption{Examples for cubic curves with varying the order of the controlling points} % \end{figure} % % \subsection{Circles and Arcs} % % All complex plotting commands in this package % use a variant of \verb+\cbezier+ as building block. As % in the \Metafont\ book circles and arcs may be represented by % \verb+\cbezier+. % % To illustrate the procedure of the macro % we do one calculation explicitely. % % E.g. we want to draw the upper right quarter of a circle with end points $z_1=(0,r)$ % and $z_4=(r,0)$. $z_2$ and $z_3$ determine the tangents. So we may introduce % them as $z_2=(h,r)$ and $z_3=(r,h)$ with a---so far unspecified---parameter % $h$. % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(50,50) % \put(20,10){\line(1,0){30}} % \put(20,10){\line(0,1){30}} % \put(20,40){\line(1,0){10}} % \put(50,10){\line(0,1){10}} % \put(30,40){\line(1,-1){20}} % \put(20,40){\makebox(0,0){$\bullet$}} % \put(50,20){\makebox(0,0){$\bullet$}} % \put(30,40){\makebox(0,0){$\bullet$}} % \put(50,10){\makebox(0,0){$\bullet$}} % \put(5,35){$z_1$} % \put(45,0){$z_4$} % \put(52,18){$z_3$} % \put(25,45){$z_2$} % \put(-5,-10){\framebox(70,70){}} % \end{picture} % \end{center} % \caption{Sketch for the geometrical configuration} % \end{figure} % % If we substitute all points in the formula for the Bernste\u\i{}n % polynomial for both components, we end at (for $t=1/2$) % \[ x[\frac{1}{2}]=y[\frac{1}{2}]=\frac{r}{2}+\frac{3h}{8}\] % These values should be $r/\sqrt{2}$ for a circle. % So we arrive at % \[ h=\frac{4}{3}\left(\sqrt{2}-1\right).\] % % \DescribeMacro{\cArc} % \DescribeMacro{\cCircle} % The plot commands are: % \begin{verbatim} % \cArc[n](xm,ym)(x1,y1) % \cCircle[n](xm,ym){r}[loc] % \end{verbatim} % % The optional qualifier $n$ determines the number % of plotted points (There are as before $n+1$ plotted points for arcs; for circles the % number depends on the specifier \textit{loc} and may be $n+1$, $2n+2$, or $4n+4$.). % % \verb+\cArc+ plots a half circle with centre $(x_m,y_m)$ and $x$-axis through % $(x_1,y_1)$ counterclockwise. % % $r$ is the radius of the circle, specified as decimal constant in terms of % \verb+\unitlength+. % % \verb+\cCircle+ plots full, halves and quarters of circles by specifying % \textit{loc} (see the corresponding table). % % \begin{table}[hbtp] % \caption{Location specifiers for \texttt{cCircle}s} % \begin{center} % \begin{tabular}{|l|l|} % \hline % \textit{loc} & specifies \dots\\ % \hline % \texttt{f} & full circle\\ % \texttt{l} & left half circle\\ % \texttt{r} & right half circle\\ % \texttt{b} & bottom half circle\\ % \texttt{t} & top half circle\\ % \texttt{lb} or \texttt{bl} & left bottom quarter of the circle\\ % \texttt{lt} or \texttt{tl} & left top quarter of the circle\\ % \texttt{rb} or \texttt{br} & right bottom quarter of the circle\\ % \texttt{rt} or \texttt{tr} & right top quarter of the circle\\ % \hline % \end{tabular} % \end{center} % \end{table} % % \begin{figure}[hbtp] % \begin{center} % \begin{picture}(300,100) % \cCircle[1600](150,50){50}[f] % \cCircle[150](100,0){50}[tr] % \cCircle[150](100,100){50}[br] % \cCircle[150](200,0){50}[tl] % \cCircle[150](200,100){50}[bl] % \cCircle[200](50,90){45}[b] % \cCircle[200](50,0){45}[t] % \cCircle[200](5,45){45}[r] % \cCircle[200](95,45){45}[l] % \cArc[200](250,70)(280,50) % \cArc[200](250,60)(280,50) % \cArc[200](250,50)(280,50) % \cArc[200](250,40)(280,50) % \cArc[200](250,30)(280,50) % \put(-10,-10){\framebox(320,120){}} % \end{picture} % \end{center} % \caption{Examples for \texttt{cCircle} and \texttt{cArc}} % \end{figure} % % % % \section{Fitting Arcs} % % The quality of representating arcs by cubic bezier curves is quite % satisfactory. The differences between circles and beziers may be % estimated in two ways. % % \begin{enumerate} % \item If we test the overall fit the area enclosed by % the curves is a good metric: The area of \texttt{Carc} for the quarter circle % is $1/30 (-33+40\sqrt{2})r^2$ to be conferred with $\pi/4\:r^2$. This is an overshot % by just 0.028\%! % \item The pointwise fit is measured by the radial difference. % The maximum is $\cong 0.00025\,r$ (at odd multiples of $\pi/8$), % it is zero for all multiples of $\pi/4$. % \end{enumerate} % % \section{Some \TeX{}nical Notes} % % For the macros therein a lot of counters and lengths have to % be declared.\footnote{Although I reuse some internal lengths I had to % declare some more to be used in function calls.} % Counters represent integer numbers, lengths are % ``real'' numbers (actually they are just integer multiples of % $1/65536=2^{-16}$). \TeX\ has just a limited number of these % stacks and therefore I use the same counters/lengths in all the macros. % % One cannot store a real number for further use in these internal stacks just a % multiplication of a \textit{decimal constant} with a length is possible (counters % may be multiplied also with real numbers but just the integer part of the decimal % constant is used!) % % The package \Lpack{calc} introduced in the \LaTeX\ Companion\cite{T4} adds a % new possiblity for multiplying lengths with the ratio of two lengths. This feature will be % utilized furthermore. % % \section{Calculating Lengths} % % If I define lengths with respect to some \verb+\unitlength+ I can now define a % product or fraction of two lengths: % % \verb+\lengthc = \lengtha*\ratio{\lengthb}{\unitlength}+ % % and % % \verb+\lengthc = \unitlenght*\ratio{\lengtha}{\lengthb}+ % % The dimension of \verb+\lengthc+ \textit{in terms of} \verb+\unitlength+ (!) is the % product, or factor respectively, of the two other lengths. % % With these operations it is even possible to % calculate square roots. Simply use the iteration scheme ($m$ integer) % \[ \xi_{m+1}=\frac{1}{2}\left( \xi_m + \frac{a}{\xi_m} \right) \] % which will converge fast (with accuracy \verb+\eps+=1\,sp) to $\sqrt a$ (starting with % $\xi_0=a>0$). % % % Lengths (in a \texttt{picture} environment) are easily calculated too, one just has to % care for the upper limits (the maximum length for \TeX\ is roughly 16384\,pt!). % % \DescribeMacro{\LenMult} % \DescribeMacro{\LenDiv} % \DescribeMacro{\AbsLen} % \DescribeMacro{\LenSqrt} % \DescribeMacro{\Length} % \DescribeMacro{\LenNorm} % The macros are: % \begin{itemize} % \item \verb+\LenMult#1#2#3+ and \verb+\LenDiv#1#2#3+ with two input and one output length % (\verb+#3+). % \item \verb+\AbsLen#1+ which returns the input length as positive length % (\TeX\ lengths can be negative!). % \item \verb+\LenSqrt#1#2+ returns in the length \verb+#2+ the square root of length \verb+#1+ % (to say it again: measured in terms of \verb+\unitlength+). % \item \verb+\Length(#1,#2)(#3,#4)#5+ stores in \verb+#5+ the length of the line % segment between points \verb+(#1,#2)+ and \verb+(#3,#4)+ (coordinates may be decimal % constants as in the \texttt{picture} commands). % \item \verb+\LenNorm#1#2#3+ returns in \verb+#3+ the length of the hypothenuse of the % rectangular triangle with catheti \verb+#1+ and \verb+#2+. % \end{itemize} % % \DescribeMacro{\eps} % \textbf{All calculations} can be only exact up to the smallest length in \TeX\ which is % \verb+\eps+=1\,sp=$2^{-16}$\,pt=0.000015\,pt. % % Examples (\verb+\unitlength+=1\,pt): % \begin{verbatim} % Mult: \LenMult{3pt}{4.333333pt}{\PathLength}\the\PathLength % Div: \LenDiv{3pt}{4.3333333pt}{\PathLength}\the\PathLength % Abs: \setlength{\PathLength}{-10pt}\the\PathLength\ % \AbsLen{\PathLength}\the\PathLength % Sqrt: \LenSqrt{16pt}{\PathLength}\the\PathLength\ % \LenSqrt{2pt}{\PathLength}\the\PathLength\ % \Length(1.5,4.3)(2.7,5){\PathLength}\the\PathLength\ % \LenNorm{3pt}{4pt}{\PathLength}\the\PathLength % \end{verbatim} % % Mult: \LenMult{3pt}{4.333333pt}{\PathLength}\the\PathLength\ (exact: 13\,pt) % % Div: \LenDiv{3pt}{4.333333pt}{\PathLength}\the\PathLength\ (exact: 0.692308\,pt) % % Abs: \setlength{\PathLength}{-10pt}\the\PathLength\ % \AbsLen{\PathLength}\the\PathLength % % Sqrt: \LenSqrt{16pt}{\PathLength}\the\PathLength\ (exact: 4\,pt)\ % \LenSqrt{2pt}{\PathLength}\the\PathLength\ (exact: 1.414213\,pt) % % \hspace*{10mm} \Length(1.5,4.3)(2.7,5){\PathLength}\the\PathLength\ (exact: 1.389244\,pt) % \LenNorm{3pt}{4pt}{\PathLength}\the\PathLength (exact: 5\,pt) % % \DescribeMacro{\PathLengthQ} % \DescribeMacro{\PathLengthC} % \DescribeMacro{\PathLength} % \DescribeMacro{\pathmax} % Furthermore you can use these macros to evaluate the length of linear interpolations % of the curves displayed by \verb+\qbezier+ and \verb+\cbezier+. The syntax is % \verb+\PathLengthQ[n](x1,y1)(x2,y2)(x3,y3)+ and\\ % \verb+\PathLengthC[n](x1,y1)(x2,y2)(x3,y3)(x4,y4)+ respectively. $n$ is the % number of interpolation points which is bounded by \verb+\pathmax+=50. The length % is stored in the% % ---already defined and used---length \verb+\PathLength+. Note: $n$ is \emph{not} optional % for these two macros. % % Example: For the cubic spline\\ % \verb+\cbezier[200](0,0)(50,100)(50,0)(100,100)+ % shown in Fig.~9 the results of the \verb+\PathLength+ \\ % for $n$=2,5,10,20,30,40,50 % are displayed below. You may increase the value of \verb+\pathmax+ as for % \verb+\qbeziermax+ but the result will due to the internal calculation problems % not become sigificant better. % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(100,80) % \put(0,0){\framebox(100,100){}} % \cbezier[300](0,0)(50,100)(50,0)(100,100) % \end{picture} % \end{center} % \caption{A nice cubic curve} % \end{figure} % % The results are: \PathLengthC[2](0,0)(50,100)(50,0)(100,100)\the\PathLength, % \PathLengthC[5](0,0)(50,100)(50,0)(100,100)\the\PathLength, % \PathLengthC[10](0,0)(50,100)(50,0)(100,100)\the\PathLength, % \PathLengthC[20](0,0)(50,100)(50,0)(100,100)\the\PathLength, % \PathLengthC[30](0,0)(50,100)(50,0)(100,100)\the\PathLength, % \PathLengthC[40](0,0)(50,100)(50,0)(100,100)\the\PathLength, % \PathLengthC[50](0,0)(50,100)(50,0)(100,100)\the\PathLength. % (An good numercial integration program will yield more accurate 149.999.) % % \section{More general arcs} % % \DescribeMacro{\cArcs} % Finally you can plot an arc (i.e.\ a cubic approximation to the circle arc) between % two points with given centre of the circle:\\ % \verb+\cArcs[n](xm,ym)(x1,y1)(x2,y2)+\\ % with $n+1$ number of points (limited by % \verb+\qbeziermax+ again) and centre $(x_m,y_m)$. % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(200,200) % \put(0,0){\framebox(200,200){}} % \put(100,100){\makebox(0,0){$\bullet$}} % \cArcs[300](100,100)(120,130)(130,120) % \cArcs[100](100,100)(150,110)(110,150) % \cArcs[300](100,100)(130,180)(130,20) % \cArcs[300](100,100)(120,170)(80,170) % \cArcs[300](100,100)(60,150)(60,50) % \cArcs[100](100,100)(90,90)(110,90) % \cArcs[200](100,100)(60,70)(130,60) % \end{picture} % \end{center} % \caption{Some examples for arcs; the centre is marked by $\bullet$} % \end{figure} % % Limitations: % \begin{itemize} % \item The arc should be smaller than the half of a circle (The limit is % handled by \verb+\cArc+ and is built-in again in \verb+\cArcs+.) Otherwise the shape % will become ``elliptic'' and ly in the wrong half plane. % \item There is no check for consistency if $r_1^2=(x_1-x_m)^2+(y_1-y_m)^2$ and % $r_2^2=(x_2-x_m)^2+(y_2-y_m)^2$ are really equal. The graph will contain in any case % both points as border points. % \end{itemize} % I will shortly derive the formulas used in the code. The code is even more tricky % due to the fact that I had just a limited number of lengths and the code reuses % some lengths explicitely and implicitely by calling routines. % % \begin{figure}[hbt] % \begin{center} % \begin{picture}(200,200) % \put(0,0){\framebox(200,200){}} % \put(80,20){\makebox(0,0){$\bullet$}} % \put(50,120){\makebox(0,0){$\bullet$}} % \put(171.65,70){\makebox(0,0){$\bullet$}} % \put(100,135){\makebox(0,0){$\bullet$}} % \put(146.65,115.825){\makebox(0,0){$\bullet$}} % \put(120.3,115.6){\makebox(0,0){$\bullet$}} % \lbezier[150](80,20)(50,120) % \lbezier[150](80,20)(171.65,70) % \cArcs[200](80,20)(50,120)(171.65,70) % \lbezier[150](50,120)(150,150) % \lbezier[150](171.65,70)(121.65,161.65) % \lbezier[30](80,20)(141.65,170) % \put(66,21){$M$} % \put(41,115){4} % \put(174,65){1} % \put(90,135){3} % \put(150,112){2} % \put(116,120){5} % \end{picture} % \end{center} % \caption{Sketch for the geometric situation} % \end{figure} % % We know the coordinates for the points $M$, 1, and 4. The tangents $\overline{43}$ and % $\overline{12}$ are normals to the radius in the corresponding points. The distances % $\overline{43}$ and $\overline{12}$ should be equal. 5 lies on the symmetry axis (dotted % line) with distance $r$ from $M$. % % \noindent Normal vectors: $\vec n_1=(y_m-y_1,x_1-x_m)$ and $\vec n_2=(y_4-y_m,x_m-x_4)$ % % \noindent Coordinate vectors: $\vec 2 = \vec 1 + \lambda \vec n_1$ and % $\vec 3 = \vec 4 + \lambda \vec n_2$ ($\lambda$ is the same because both normal % vectors have length $r$) % % \noindent Furthermore $\vec 5={\cal B}_4 [1/2]$ (the cubic spline % should also be symmetric and contain 5) % % Now we have: % \begin{eqnarray} % x[ t] & = & (1-t)^3 x_1 + 3 t (1-t)^2 x_2 + 3 t^2 (1-t) x_3 +t^3 x_4\\ % y[ t] & = & (1-t)^3 y_1 + 3 t (1-t)^2 y_2 + 3 t^2 (1-t) y_3 +t^3 y_4 % \end{eqnarray} % % Substituting for $x_2$, $y_2$, $x_3$, and $y_3$ and $t\to1/2$: % \begin{eqnarray} % x_5=x\left[ \frac{1}{2}\right] & = & \frac{1}{2} % (x_1 +x_4) + \frac{3}{8} \lambda(y_4-y_1) \\ % y_5=y\left[ \frac{1}{2}\right] & = & \frac{1}{2} % (y_1 +y_4) + \frac{3}{8} \lambda(x_1-x_4 ) % \end{eqnarray} % % We could now calculate the norm of this point and set it equal to the radius $r^2= % (x_m-x_1)^2+(y_m-y_1)^2$. This gives a quadratic equation for % $\lambda$. But the result is a rather complex term with respect to our input parameters. % % A nicer term can be found if we define % \begin{equation} % x_5=x_m+\kappa (x_1+x_4-2x_m) \quad y_5=y_m+\kappa (y_1+y_4-2y_m) % \end{equation} % with aid of the symmetry vector. $\kappa$ is simply $r$ divided by the norm of the % symmetry vector. % % The resulting $\lambda$ is now (using just the $x$-equation) % \begin{equation} % \lambda=\frac{4}{3} (-1+2 \kappa)\frac{x_1+x_4-2x_m}{y_4-y_1} % \end{equation} % % Special cases: % \begin{itemize} % \item The symmetry vector is the null vector if $\overline{14}$ is a diameter of the % circle. But this case is already solved by \verb+\cArc+. % \item For $y_4=y_1$ one needs the equation for the $y$-component, i.e.\ we have as factor % $(y_1+y_4-2y_m)/(x_1-x_4)$ in $\lambda$. % \end{itemize} % % % \section{Varying the line thickness} % % There is another package, \Lpack{bez123}\cite{T5}, which introduces also linear and cubic % bezier curves, even variants which plot exactly all kind of conic curves (ellipses, % parabolas, and hyperbolas). There are two features in \Lpack{bez123}, which I added in the % third version of \Lpack{ebezier}: % % \DescribeMacro{\thinlines} % \DescribeMacro{\thicklines} % \DescribeMacro{\linethickness} % \DescribeMacro{\qbeziermax} % \begin{enumerate} % \item Changing the size of the plot squares by the \LaTeX\ commands\\ % \verb+\thinlines+, \verb+\thicklines+, and/or \verb+\linethickness+. % \item Calulation of an optimal number of plot points if $n$=0 instead of using the % maximum \verb+\qbeziermax+ (see next section). % \end{enumerate} % % If you look close to lines you will note some peculiarity. For instance the original % \LaTeX\ \verb+\line+ is in horizontal/vertical mode a simple \verb+\ruler+. % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(100,100) % \thinlines % \put(-5,-5){\framebox(110,110){}} % \setlength{\linethickness}{0.1pt} % \put(0,10){\line(1,0){100}} % \put(10,0){\line(0,1){100}} % \setlength{\linethickness}{10pt} % \put(10,10){\line(1,0){60}} % \put(10,10){\line(0,1){60}} % \end{picture} % \end{center} % \caption{Axes with standard lines} % \end{figure} % % Remark: The \textit{line} is exactly as long as specified. % % \DescribeMacro{\@wholewidth} % But the plot point used by \verb+\qbezier+, \Lpack{bez123} and \Lpack{ebezier} % (until version 2!) is a small square which is not centered at the control points % (dimension \verb+\@wholewidth+) % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(50,50) % \thinlines % \put(-5,-5){\framebox(60,60){}} % \setlength{\linethickness}{0.1pt} % \put(0,25){\line(1,0){50}} % \put(15,0){\line(0,1){50}} % \DefOldPlotSymbol % \setlength{\linethickness}{10pt} % \lbezier[1](15,25)(15,25) % \end{picture} % \end{center} % \caption{Old plot symbol} % \end{figure} % % which results in a shifted $y$-axis and \textit{lines} which are actually longer % by an amount of one square (i.e. \verb+\@wholewidth+) % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(100,100) % \thinlines % \put(-5,-5){\framebox(110,110){}} % \setlength{\linethickness}{0.1pt} % \put(0,10){\line(1,0){100}} % \put(10,0){\line(0,1){100}} % \setlength{\linethickness}{10pt} % \DefOldPlotSymbol % \setlength{\linethickness}{10pt} % \lbezier[10](10,10)(80,10) % \lbezier[10](10,10)(10,80) % \end{picture} % \end{center} % \caption{Axes with old plot symbol} % \end{figure} % % or with hollow squares ($\bullet$ references to the end points). % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(100,100) % \thinlines % \put(-5,-5){\framebox(110,110){}} % \setlength{\linethickness}{0.1pt} % \put(0,10){\line(1,0){100}} % \put(10,0){\line(0,1){100}} % \thinlines % \put(10,5){\framebox(70,10){}} % \put(10,5){\framebox(10,70){}} % \put(10,5){\framebox(10,10){}} % \put(70,5){\framebox(10,10){}} % \put(10,65){\framebox(10,10){}} % \put(10,10){\makebox(0,0){$\bullet$}} % \put(70,10){\makebox(0,0){$\bullet$}} % \put(10,70){\makebox(0,0){$\bullet$}} % \end{picture} % \end{center} % \caption{Axes with old plot symbol (hollow)} % \end{figure} % % % This version uses centered plot symbols (standard is again a square) % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(50,50) % \put(-5,-5){\framebox(60,60){}} % \setlength{\linethickness}{0.1pt} % \put(0,25){\line(1,0){50}} % \put(25,0){\line(0,1){50}} % \DefStandardPlotSymbol % \setlength{\linethickness}{10pt} % \lbezier[1](25,25,)(25,25) % \end{picture} % \end{center} % \caption{New standard plot symbol} % \end{figure} % % which corrects the shift of the $y$-axis. The line is again longer but this % time the excess is symmetrically on both ends % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(100,100) % \thinlines % \put(-5,-5){\framebox(110,110){}} % \setlength{\linethickness}{0.1pt} % \put(0,10){\line(1,0){100}} % \put(10,0){\line(0,1){100}} % \setlength{\linethickness}{10pt} % \lbezier[10](10,10)(80,10) % \lbezier[10](10,10)(10,80) % \end{picture} % \end{center} % \caption{Axes with new standard plot symbol} % \end{figure} % % or again with hollow squares. % % \begin{figure}[htbp] % \begin{center} % \begin{picture}(100,100) % \thinlines % \put(-5,-5){\framebox(110,110){}} % \setlength{\linethickness}{0.1pt} % \put(0,10){\line(1,0){100}} % \put(10,0){\line(0,1){100}} % \thinlines % \put(5,5){\framebox(70,10){}} % \put(5,5){\framebox(10,70){}} % \put(5,5){\framebox(10,10){}} % \put(65,5){\framebox(10,10){}} % \put(5,65){\framebox(10,10){}} % \put(10,10){\makebox(0,0){$\bullet$}} % \put(70,10){\makebox(0,0){$\bullet$}} % \put(10,70){\makebox(0,0){$\bullet$}} % \end{picture} % \end{center} % \caption{Axes with new standard plot symbol (hollow)} % \end{figure} % % \DescribeMacro{\DefOldPlotSymbol} % \DescribeMacro{\Qbezier} % To be consistent with the old version the command \verb+\DefOldPlotSymbol+ % is supplied which uses the old form. Also a variant \verb+\Qbezier+ for % \verb+\qbezier+ is % defined which can use the new plot symbol.\footnote{This command is just for convenience. % A quadratic bezier can be plotted as cubic bezier as follows. If you want to plot % $\backslash$\texttt{qbezier[100](z1)(zm)(z4)} with $(z)=(x,y)$ you may calulate points % $z_2=2/3[z_m,z_1]$ and $z_3=2/3[z_m,z_4]$. The cubic bezier $\backslash$% % \texttt{cbezier[100](z1)(z2)(z3)(z4)} is exactly the same as the quadratic one!}% % \footnote{It can also use the other new symbols defined later.} % % The next point of consideration is the handling of slanted lines. % In the ordinary \LaTeX-\texttt{picture} environment % \verb+\linethickness+ has no effect on slanted lines. Now the change applies % but a new problem occurs. If you plot a slanted line (slope angle $\varphi$) % with squares % % \begin{figure}[htb] % \begin{center} % \begin{picture}(100,80) % \thinlines % \put(-5,-5){\framebox(110,90){}} % \put(5,5){\framebox(30,30){}} % \put(25,15){\framebox(30,30){}} % \put(45,25){\framebox(30,30){}} % \put(65,35){\framebox(30,30){}} % \put(35,5){\line(2,1){70}} % \put(5,35){\line(2,1){70}} % \put(60,5){\vector(-1,2){5}} % \put(55,15){\line(-1,2){23}} % \put(32.5,60){\vector(1,-2){5}} % \put(61,22){$\scriptscriptstyle\varphi$} % \put(32,47){$\scriptscriptstyle\varphi$} % \put(65,10){$d$} % \end{picture} % \end{center} % \caption{Effective thickness for slanted lines} % \end{figure} % % your line gets effective thicker! The factor of enlargement is $\sin \varphi % +\cos \varphi$ which has its maximum $\sqrt 2$ with slope $\varphi_0=45^0$. % % % There are two possiblities to correct the thickness % \begin{itemize} % \item correct the line thickness of each line or % \item use other plot symbols which behave better. % \end{itemize} % % \DescribeMacro{\Lbezier} % The first possibilitiy can be realized just for \verb+\lbezier+ and not % \verb+\cbezier+ because the slope changes from point to point in the latter case. % The solution is established by internally changing the \verb+\linethickness+ % by the factor $\ell/(\Delta x+\Delta y)$ where $\ell$ denotes the length of the % line ($=\sqrt{\Delta^2 x +\Delta^2 y}$) % and $\Delta x$ is the horizontal difference of the the points % ($\Delta y$ respectivelly for the vertical difference). % % To use this line type call \verb+\Lbezier[n](x1,y1)(x2,y2)+. % % The second chance is to change the plot symbol to a disc. The smallest disk % available is the character ``.'' at 5pt. Unfortunately this method will % implicitely restrict the \verb+\linethickness+ to some definite values (see the % following table for the numbers in question). % % \begin{table}[hbtp] % \caption{Dimensions for various plot symbols} % \begin{center} % \begin{tabular}{|ll|rr|l|} % \hline % Font&Size for (10pt) & Width & Heigth & Rule \\ % \hline % \verb+\vrm+ &tiny& \SB{\vrm}{.}\the\wd1 & \SB{\vrm}{.}\the\ht1 & % \SB{\vrm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\virm+ &tiny for 11/12pt& \SB{\virm}{.}\the\wd1 & \SB{\virm}{.}\the\ht1 & % \SB{\virm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\viirm+ & scriptsize &\SB{\viirm}{.}\the\wd1 & \SB{\viirm}{.}\the\ht1 & % \SB{\viirm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\viiirm+ & footnotesize & \SB{\viiirm}{.}\the\wd1 & \SB{\viiirm}{.}\the\ht1 & % \SB{\viiirm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\ixrm+ & small &\SB{\ixrm}{.}\the\wd1 & \SB{\ixrm}{.}\the\ht1 & % \SB{\ixrm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xrm+ & normalsize &\SB{\xrm}{.}\the\wd1 & \SB{\xrm}{.}\the\ht1 & % \SB{\xrm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xirm+ & normalsize 11pt& \SB{\xirm}{.}\the\wd1 & \SB{\xirm}{.}\the\ht1 & % \SB{\xirm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xiirm+ & large &\SB{\xiirm}{.}\the\wd1 & \SB{\xiirm}{.}\the\ht1 & % \SB{\xiirm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xivrm+ & Large & \SB{\xivrm}{.}\the\wd1 & \SB{\xivrm}{.}\the\ht1 & % \SB{\xivrm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xviirm+ & LARGE &\SB{\xviirm}{.}\the\wd1 & \SB{\xviirm}{.}\the\ht1 & % \SB{\xviirm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xxrm+ & huge &\SB{\xxrm}{.}\the\wd1 & \SB{\xxrm}{.}\the\ht1 & % \SB{\xxrm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+\xxvrm+ & Huge &\SB{\xxvrm}{.}\the\wd1 & \SB{\xxvrm}{.}\the\ht1 & % \SB{\xxvrm}{.}\rule{1 cm}{\ht1} \copy1\\ % \verb+$\bullet$+ & &\SB{$\bullet$}{}\the\wd1 &\SB{$\bullet$}{}\the\ht1& % \SB{$\bullet$}{}\rule{1cm}{\ht1} \copy1\\ % \hline % \end{tabular} % \end{center} % \end{table} % % \DescribeMacro{\DefPlotSymbol} % With the aim of the command \verb+\DefPlotSymbol{item}+ you may define any % \textit{item} as your plot symbol\footnote{A similar approach with centered % symbols can be found in the packages % \Lpack{epic}\cite{epic} and PiC\TeX\cite{pictex}.}. % It will be centered as the default plot square % (otherwise an even larger shift of the $y$-axis would occur). Use explicit font % selection with the names supplied in the table to ensure style independence % (otherwise e.g.\ % \verb+\DefPlotSymbol{\tiny .}+ would be different in 10pt and 11pt context). % % \DescribeMacro{\DefShiftedPlotSymbol} % This works % for all \textit{items} which have a vertical symmetry axis with respect to their % defining bounding box (defined by \Metafont) and which ly on the baseline % (or beyond if they have some defined depth). It will not work otherwise. For example the % circles from the circle font have heigth and depth zero and their reference point is % already the centre (i.e. the symbol extends backward). Or consider the ``*''-sign. % It does not ly on the baseline. For these cases a generalized command is supplied:\\ % \verb+\DefShiftedPlotSymbol{item}{x-shift}{y-shift}{height}+. % % The shifts are applied % to the left and downward. The supplied heigth will only have effect if you specify % $n=0$ for the number of plotting points. % % Examples: % \begin{verbatim} % \DefShiftedPlotSymbol{\tencirc n}{0pt}{0pt}{1pt} % \DefShiftedPlotSymbol{\tencirc \char'176}{0pt}{0pt}{15pt} % \DefShiftedPlotSymbol{\fbox{\Huge *}}{0pt}{0pt}{25pt} % %with bounding box % \setbox0=\hbox{*} % \DefShiftedPlotSymbol{*}{.5\wd0}{.7\ht0}{.6\ht0} % \lbezier[1](100,30)(100,30) % \lbezier[0](0,20)(125,20) % \DefShiftedPlotSymbol{*}{.5\wd0}{.7\ht0}{10\ht0} % \lbezier[0](0,10)(125,10) % \end{verbatim} % % \setlength{\fboxsep}{0pt} % \setlength{\fboxrule}{0.1pt} % % \begin{figure}[hbtp] % \begin{center} % \begin{picture}(125,50) % \put(-5,-5){\framebox(135,60){}} % \setlength{\linethickness}{0.1pt} % \put(0,30){\line(1,0){125}} % \multiput(25,20)(25,0){4}{\line(0,1){20}} % \DefShiftedPlotSymbol{\tencirc n}{0pt}{0pt}{1pt} % \lbezier[1](25,30)(25,30) % \DefShiftedPlotSymbol{\tencirc \char'176}{0pt}{0pt}{15pt} % \lbezier[1](50,30)(50,30) % \DefShiftedPlotSymbol{\fbox{\Huge *}}{0pt}{0pt}{25pt} % \lbezier[1](75,30)(75,30) % \setbox0=\hbox{*} % \DefShiftedPlotSymbol{*}{.5\wd0}{.7\ht0}{.6\ht0} % \lbezier[1](100,30)(100,30) % \lbezier[0](0,20)(125,20) % \DefShiftedPlotSymbol{*}{.5\wd0}{.7\ht0}{10\ht0} % \lbezier[0](0,10)(125,10) % \end{picture} % \end{center} % \caption{Examples for other plot symbols} % \end{figure} % % \emph{Caution:} The commands for changing the line thickness have % implicit effects for plot symbols % defined with \verb+\DefPlotSymbol{item}+ or \\ % \verb+\DefShiftedPlotSymbol+. The implicit or % explicit defined height is redefined. But the effect is only visible in case $n=0$. % % % \DescribeMacro{\DefStandardPlotSymbol} % In any case you may restore \textbf{default values} by stating % \begin{verbatim} % \DefStandardPlotSymbol % \thinlines % \end{verbatim} % % \section{Estimation for the number of plotting points} % % As mentioned in the last section all plotting macros will calculate the number % of plotting points if the value $n=0$ is active. All calculations will % use the actual length of the object which can % be calculated with the aim of the calculation macros in Section \textit{Calculating Lengths}. % For all these calculations \verb+\eps+ is temporarily increased by a factor of 10 and % for higher bezier curves just 5 intermediate points will be used. If the calculated number % exceeds the specified maximum \verb+\qbeziermax+ an info in the log-file will be generated. % % All macros for circles and arcs will use a simpler estimate due to their construction % by an intrinsic call of the cubic bezier. It uses the length of the chord and % the maximal deviation factor $\pi/2$ from the arc length. % % % \section{Joining linear beziers} % % \DescribeMacro{\ljoin} % A further command has been supplied to ease the drawing of polygon paths. Instead of % writing a sequence of \verb+\lbezier+s with common vertices you can write compactly % \verb+\ljoin[n](x1,y1)(x2,y2)(x3,y3)...(xm,ym)+ % % Caution: There should be no spaces in the command, so break lines with \% if % necessary. There should be at least 2 points. The parameter $n$ is optional, internally % \verb-\lbezier[n](xk,yk)(xk+1,yk+1)- will be executed. % % \DescribeMacro{\Ljoin} % There is also a variant \verb+\Ljoin+ which uses \verb+\Lbezier+. % % \renewcommand{\qbeziermax}{1200} % \begin{figure} % \begin{center} % \begin{picture}(200,100) % \put(-5,-5){\framebox(210,110){}} % \begin{picture}(100,100) % \ljoin(0,0)(20,100)(20,0)(40,50)(40,0)(60,25)(60,0)(80,12.5)(80,0)(100,6.25)(100,0) % \end{picture} % \begin{picture}(100,100) % \Ljoin(0,0)(20,100)(20,0)(40,50)(40,0)(60,25)(60,0)% % (80,12.5)(80,0)(100,6.25)(100,0) % \end{picture} % \end{picture} % \end{center} % \caption{$\backslash$\texttt{ljoin} versus $\backslash$\texttt{Ljoin}} % \end{figure} % % \changes{Version 1}{2000/07/28}{original version} % \changes{Version 2}{2001/12/04}{major bug fix for cCircle} % \changes{Version 3}{2002/10/23}{major changes} % \changes{Version 4}{2005/03/01}{minor changes} % % \section*{Versions} % % This is Version 4 from March 1, 2004. % % Changes with regard to version 3: % \begin{itemize} % \item Bug-address changed. % \item Error in defining (first) equation corrected (thanks to \verb+jens.schwaiger@uni-graz.at+). % \item Marginal corrections with regard to \Lpack{l2tabu} (v1.8). % \item Documentaion as pdf supplied. % \end{itemize} % % Changes with regard to version 2: % \begin{itemize} % \item Implementing line thickness (\verb+\thinlines+, \verb+\thicklines+, and\\ % \verb+\setlength{\linethickness}{dimen}+. % \item Different plot symbols. % \item \verb+\Lbezier+ for equally thick lines in all directions. % \item \verb+\Qbezier+ implementation to be used with new plot symbols. % \item Calculation of an optimal number of plot symbols (as default number for case $n$=0). % \item Parameter $n$ is for all \emph{plot} commands optional. % \item New macro for polygon paths. % \item Style supplied in dtx-format. % \item Minor style changes regarding numbers and lengths. % \end{itemize} % % Changes with regard to Version 1: % \begin{itemize} % \item \verb+\@tempa+ replaced by \verb+\@TempDim+. \verb+\@tempa+ was also % used by other packages. % \item Additionaly supplied \verb+\RequirePackage{calc}+. % \item Bug fixed for circles. The original macros did actually not support changes in % \verb+\unitlength+. % \end{itemize} % % \begin{thebibliography}{9} % \bibitem{T2} D.\ E.\ Knuth: \textit{The} \TeX\ \textit{Book}, Addison-Wesley, % Reading MA, 1986. % \bibitem{T3} D.\ E.\ Knuth: \textit{The} \Metafont\ \textit{Book}, Addison-Wesley, % Reading MA, 1986. % \bibitem{T4} M.\ Goossens, F.\ Mittelbach, A.\ Samarin: \textit{The} \LaTeX\ \textit{Companion}, % Addison-Wesley, Reading MA, 1994. % \bibitem{T1} M.\ Goossens, S.\ Rahtz, F.\ Mittelbach: \textit{The} \LaTeX\ % \textit{Graphics Companion}, Addison-Wesley, Reading MA, 1997. % \bibitem{T5} P.\ Wilson: \textit{The} \Lpack{bez123} \textit{and} \Lpack{multiply} % \textit{packages}, 1998;\\ packages at CTAN/macros/latex/contrib/supported/bez123. % \bibitem{epic} S.\ Podar: \textit{Enhancements to the Picture Environment % in }\LaTeX, 1986;\\ package at CTAN/macros/latex/other/epic. % \bibitem{pictex} M.\ J.\ Wichura: \textit{The PiC}\TeX\ \textit{Manual}, 1992;\\ % package at CTAN/graphics/pictex. % \bibitem{pict2e} R.\ Niepraschk, H.\ Gaesslein: The \Lpack{pict2e} Package, 2003;\\ % package at CTAN/macros/latex/contrib/pict2e. % \bibitem{PiX} N.\ J.\ H.\ M.\ van Beurden: A \LaTeX\ picture editor for Windows, 2003;\\ % package at CTAN/systems/win32/latexpix. % \end{thebibliography} % % \OnlyDescription % % \section{Implementation} % % The macros \verb+\lbezier+ and \verb+\cbezier+ are rather old, they existed since % I realized the existence of \Lpack{bezier.sty} more then ten years ago. Therefore % the macros are written rather in pure \TeX\ than in \LaTeX. Only the calculation % macros demand for \LaTeX\ notation to use the package \Lpack{calc}. But with this % version the macros interact more and some \LaTeX\ part occurrs also in the plot macros. % % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e} \RequirePackage{calc} %% % \end{macrocode} % I define new font names because \texttt{cmr} may not be the standard font. They % may be needed for plotting symbols. % \begin{macrocode} \newfont{\vrm}{cmr5} \newfont{\virm}{cmr6} \newfont{\viirm}{cmr7} \newfont{\viiirm}{cmr8} \newfont{\ixrm}{cmr9} \newfont{\xrm}{cmr10} \newfont{\xiirm}{cmr12} \newfont{\xviirm}{cmr17} \newfont{\xirm}{cmr10 scaled \magstephalf} \newfont{\xivrm}{cmr10 scaled \magstep2} \newfont{\xxrm}{cmr10 scaled \magstep4} \newfont{\xxvrm}{cmr10 scaled \magstep5} %% % \end{macrocode} % % I need only three new counters, % \begin{macrocode} \newcounter{@cnta}\newcounter{@cntb}\newcounter{@cntc}\newcounter{@cntd} %% % \end{macrocode} % but a lot of lengths. Packages like PiC\TeX\ have problems by defining too many % lengths, so I try to use as many already defined lengths (defined for usage % in a plotting context). % \begin{macrocode} %% \@TempDim#1#2#3{"count"|"dimen"|"box"|"skip"}{\myname}{\realname} %% allocate new one or alias is defined, so use it %% \def\@TempDim#1#2#3{% \ifx\@und@fined#3\csname new#1\endcsname#2% \else\let#2#3\fi} %% \@TempDim{dimen}\@X\@ovxx \@TempDim{dimen}\@Xa\@ovdx \@TempDim{dimen}\@Xb\@ovyy \@TempDim{dimen}\@Xc\@ovdy \@TempDim{dimen}\@Y\@ovro \@TempDim{dimen}\@Ya\@ovri \@TempDim{dimen}\@Yb\@xdim \@TempDim{dimen}\@Yc\@ydim \@TempDim{dimen}\@Z\@clnht \@TempDim{dimen}\@Za\@clnwd \@TempDim{dimen}\@Zb\@dashdim \@TempDim{dimen}\@Zc\@tempdima \@TempDim{dimen}\@Zd\@tempdimb \@TempDim{dimen}\@Ze\@tempdimc %% \newlength{\@Zf}\newlength{\@Zg}\newlength{\@Zh} \newlength{\@Zi}\newlength{\@Zj} % \end{macrocode} % % This special length will be used for the circle macros. The magic number is % $0.55228474983=4/3 (\sqrt{2}-1)$. % % \begin{macrocode} \newlength{\magicnum} \newcommand\set@magic{% \setlength{\magicnum}{0.55228474983\unitlength}} %% % \end{macrocode} % % Another special one is \verb+\eps+. It could be initialized by \verb+\eps\@ne+ % but due to its context to the calculation part 1sp=1/65536pt is used. % % \begin{macrocode} \newlength{\eps} \setlength{\eps}{1sp} %% % \end{macrocode} % % The last one is \verb+\PathLength+. It stores lengths which the user may need for % further use. % % \begin{macrocode} \newlength{\PathLength} %% % \end{macrocode} % % This two constants are needed in calculations, but I did not want to waste % any additional counter. \verb+\pathmax+ may be redefined to exceed 256, so it % is not defined by \verb+\chardef+. % % \begin{macrocode} \chardef\x@=10 \newcommand{\pathmax}{50} %% % \end{macrocode} % % This fundamental box will keep the plotting symbol. % % \begin{macrocode} \newsavebox{\@pt} %% % \end{macrocode} % % I have to distinguish three cases: standard plot symbol, old standard plot symbol, % or any new one. For this purpose I need two logicals. % % \begin{macrocode} \newif\if@other@symbol \newif\if@standard@symbol % \end{macrocode} % % All plot symbols may be defined by the most general one,\\ % \verb+\DefShiftedPlotSymbol+, but this way may be faster. The % other important macro is \verb+\set@width+ which redefines the plot % box due to changes which may have occurred (line thickness). % % \begin{macrocode} \newcommand{\DefStandardPlotSymbol}{% \@other@symbolfalse\@standard@symboltrue \setbox\@pt\hbox{\hskip -.5\wd0\vrule height\@halfwidth depth\@halfwidth width\@wholewidth}} \newcommand{\DefOldPlotSymbol}{% \@other@symbolfalse\@standard@symbolfalse \setbox\@pt\hbox{\vrule height\@halfwidth depth\@halfwidth width\@wholewidth}} \newcommand{\DefPlotSymbol}[1]{\setbox0=\hbox{#1}\@X\ht0\advance\@X-\dp0 \@halfwidth.5\ht0\@wholewidth\ht0 \@other@symboltrue\@standard@symbolfalse \setbox\@pt\hbox{\hskip -.5\wd0\lower.5\@X\copy0}} \newcommand{\DefShiftedPlotSymbol}[4]{\setbox0=\hbox{#1}\@X #2\@Y #3 \@wholewidth #4\@halfwidth.5\@wholewidth \@other@symboltrue\@standard@symbolfalse \setbox\@pt\hbox{\hskip-\@X\lower\@Y\copy0}} \newcommand{\set@width}{% \if@other@symbol \relax \else \if@standard@symbol \@X-.5\@wholewidth \else \@X\z@ \fi \setbox\@pt\hbox{\hskip\@X\vrule height\@halfwidth depth\@halfwidth width\@wholewidth}% \fi} %% % \end{macrocode} % % The initialization is done here. Note that \verb+\thinlines+ % is already default and needs not be specified here. % % \begin{macrocode} \DefStandardPlotSymbol %% % \end{macrocode} % % All plot macros have an optional number. Therefore an additional internal macro % is needed (it will have the same name with an extra @ in front of it. % % Here is the simpliest one, the linear case. % % \begin{macrocode} \def\lbezier{\@ifnextchar [{\@lbezier}{\@lbezier[0]}} \def\@lbezier[#1](#2,#3)(#4,#5){% \c@@cntc#1\relax \ifnum \c@@cntc<\@ne % \end{macrocode} % % I decrease the precision locally to speed up calculations. We need just % an estimate. % % \begin{macrocode} \multiply\eps\x@ \Length(#2,#3)(#4,#5){\PathLength}% \divide\eps\x@ \c@@cntc\PathLength \@X.5\@halfwidth \divide\c@@cntc\@X \ifnum \c@@cntc>\qbeziermax% \PackageInfo{ebezier}{\the\c@@cntc\space points needed exceeding % qbeziermax=\qbeziermax!}\fi \fi \ifnum \c@@cntc>\qbeziermax \c@@cntc\qbeziermax\relax \PackageWarning{ebezier}{Counter reset to qbeziermax=\qbeziermax!}\fi \c@@cnta\c@@cntc\relax\advance\c@@cnta\@ne \@Xa #4\unitlength \advance\@Xa-#2\unitlength \divide\@Xa\c@@cntc \@Ya #5\unitlength \advance\@Ya-#3\unitlength \divide\@Ya\c@@cntc \c@@cntb\z@\relax \set@width \put(#2,#3){\@whilenum{\c@@cntb<\c@@cnta}\do {\@X\c@@cntb \@Xa\@Y \c@@cntb\@Ya \raise\@Y\hbox to\z@{\hskip\@X\unhcopy\@pt\hss}% \advance\c@@cntb\@ne}}} %% % \end{macrocode} % % \verb+\Lbezier+ changes the line thickness. It is stored in \verb+\@Xb+. % % \begin{macrocode} \def\Lbezier{\@ifnextchar [{\@Lbezier}{\@Lbezier[0]}} \def\@Lbezier[#1](#2,#3)(#4,#5){\c@@cntc#1\relax \@Xb\@wholewidth \@X #4\unitlength \advance\@X-#2\unitlength \AbsLen{\@X}% \@Y #5\unitlength \advance\@Y-#3\unitlength \AbsLen{\@Y}% \LenNorm{\@X}{\@Y}{\@Xc}\LenMult{\@Xc}{\@wholewidth}{\@Yb}% \LenDiv{\@Yb}{\@X+\@Y}{\@wholewidth}\@halfwidth .5\@wholewidth \ifnum \c@@cntc<\@ne \multiply\eps\x@ \Length(#2,#3)(#4,#5){\PathLength}% \divide\eps\x@ \c@@cntc\PathLength \@X.5\@halfwidth \divide\c@@cntc\@X \ifnum \c@@cntc>\qbeziermax% \PackageInfo{ebezier}{\the\c@@cntc\space points needed exceeding % qbeziermax=\qbeziermax!}\fi \fi \ifnum \c@@cntc>\qbeziermax \c@@cntc\qbeziermax\relax \PackageWarning{ebezier}{Counter reset to qbeziermax=\qbeziermax!}\fi \c@@cnta\c@@cntc\relax \advance\c@@cnta\@ne \@Xa #4\unitlength \advance\@Xa-#2\unitlength \divide\@Xa\c@@cntc \@Ya #5\unitlength \advance\@Ya-#3\unitlength \divide\@Ya\c@@cntc \c@@cntb\z@\relax \set@width \put(#2,#3){\@whilenum{\c@@cntb<\c@@cnta}\do {\@X\c@@cntb \@Xa\@Y \c@@cntb\@Ya \raise\@Y\hbox to\z@{\hskip\@X\unhcopy\@pt\hss}% \advance\c@@cntb\@ne}} \@wholewidth\@Xb \@halfwidth .5\@Xb} %% % \end{macrocode} % % The two joining macros need two internal steps to process an implicit list. % % \begin{macrocode} \def\ljoin{\@ifnextchar [{\@ljoin}{\@ljoin[0]}} \def\@ljoin[#1](#2,#3){\@ifnextchar ({\l@join[#1](#2,#3)}{\relax}} \def\l@join[#1](#2,#3)(#4,#5){% \lbezier[#1](#2,#3)(#4,#5)% \ljoin[#1](#4,#5)} %% \def\Ljoin{\@ifnextchar [{\@Ljoin}{\@Ljoin[0]}} \def\@Ljoin[#1](#2,#3){\@ifnextchar ({\L@join[#1](#2,#3)}{\relax}} \def\L@join[#1](#2,#3)(#4,#5){% \Lbezier[#1](#2,#3)(#4,#5)% \Ljoin[#1](#4,#5)} %% % \end{macrocode} % % \verb+\Qbezier+ is defined, because \verb+\qbezier+ uses an other plot box. % The original macro is a little bit more complicated to handle extra spaces % but I hope this will suffice. % % \begin{macrocode} \def\Qbezier{\@ifnextchar [{\@Qbezier}{\@Qbezier[0]}} \def\@Qbezier[#1](#2,#3)(#4,#5)(#6,#7){\c@@cntc#1\relax \ifnum \c@@cntc<\@ne \multiply\eps\x@ \PathLengthQ[5](#2,#3)(#4,#5)(#6,#7)% \divide\eps\x@ \c@@cntc\PathLength \@X.5\@halfwidth \divide\c@@cntc\@X \ifnum \c@@cntc>\qbeziermax% \PackageInfo{ebezier}{\the\c@@cntc\space points needed exceeding % qbeziermax=\qbeziermax!}\fi \fi \ifnum \c@@cntc>\qbeziermax \c@@cntc\qbeziermax\relax \PackageWarning{ebezier}{Counter reset to qbeziermax=\qbeziermax!}\fi \c@@cnta\c@@cntc\relax \advance\c@@cnta\@ne \@Xa #4\unitlength \advance\@Xa-#2\unitlength \multiply\@Xa\tw@ \@Xb #6\unitlength \advance\@Xb-#2\unitlength \advance\@Xb-\@Xa \divide\@Xb\c@@cntc \@Ya #5\unitlength \advance\@Ya-#3\unitlength \multiply\@Ya\tw@ \@Yb #7\unitlength \advance\@Yb-#3\unitlength \advance\@Yb-\@Ya \divide\@Yb\c@@cntc \c@@cntb\z@\relax \set@width \put(#2,#3){\@whilenum{\c@@cntb<\c@@cnta}\do {\@X\c@@cntb \@Xb\@Y \c@@cntb\@Yb \advance\@X\@Xa \advance\@Y\@Ya \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \raise \@Y \hb@xt@\z@{\kern\@X\unhcopy\@pt\hss}% \advance\c@@cntb\@ne}}} %% % \end{macrocode} % % \verb+\cbezier+ is the most complex command. All calculations have to be % done in the correct order to minimize overflow conditions. % % \begin{macrocode} \def\cbezier{\@ifnextchar [{\@cbezier}{\@cbezier[0]}} \def\@cbezier[#1](#2,#3)(#4,#5)(#6,#7)(#8,#9){% \c@@cntc#1\relax \ifnum \c@@cntc<\@ne \multiply\eps\x@ \PathLengthC[5](#2,#3)(#4,#5)(#6,#7)(#8,#9)% \divide\eps\x@ \c@@cntc\PathLength \@X = 0.5\@halfwidth \divide\c@@cntc\@X \ifnum \c@@cntc>\qbeziermax% \PackageInfo{ebezier}{\the\c@@cntc\space points needed exceeding % qbeziermax=\qbeziermax!}\fi \fi \ifnum \c@@cntc>\qbeziermax \c@@cntc\qbeziermax\relax \PackageWarning{ebezier}{Counter reset to qbeziermax=\qbeziermax!}\fi \c@@cnta\c@@cntc\relax \advance\c@@cnta\@ne \@Xa #4\unitlength \advance\@Xa-#2\unitlength \multiply\@Xa\thr@@ \@Xb #6\unitlength \advance\@Xb-#2\unitlength \multiply\@Xb\thr@@ \advance\@Xb -2\@Xa \@Xc #8\unitlength \advance\@Xc-#2\unitlength \advance\@Xc-\@Xa \advance\@Xc-\@Xb \@Ya #5\unitlength \advance\@Ya-#3\unitlength \multiply\@Ya\thr@@ \@Yb #7\unitlength \advance\@Yb-#3\unitlength \multiply\@Yb\thr@@ \advance\@Yb-2\@Ya \@Yc #9\unitlength \advance\@Yc-#3\unitlength \advance\@Yc-\@Ya \advance\@Yc-\@Yb \divide\@Xc\c@@cntc \divide\@Yc\c@@cntc \c@@cntb\z@\relax \set@width \put(#2,#3){\@whilenum{\c@@cntb<\c@@cnta}\do {\@X\c@@cntb \@Xc\@Y \c@@cntb\@Yc \advance\@X\@Xb \advance\@Y\@Yb \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \advance\@X\@Xa \advance\@Y\@Ya \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \raise \@Y \hbox to \z@{\hskip \@X\unhcopy\@pt\hss}% \advance\c@@cntb\@ne}}} %% % \end{macrocode} % % \verb+\Cbezier+ changes the plot symbol so a restore is needed. But it will % not keep the original one! % % \begin{macrocode} \def\Cbezier{\@ifnextchar [{\@Cbezier}{\@Cbezier[0]}} \def\@Cbezier[#1](#2,#3)(#4,#5)(#6,#7)(#8,#9){% \cbezier[#1](#2,#3)(#4,#5)(#6,#7)(#8,#9)% \c@@cntc#1\relax\divide\c@@cntc\thr@@ \lbezier[\c@@cntc](#2,#3)(#4,#5)% \lbezier[\c@@cntc](#4,#5)(#6,#7)% \lbezier[\c@@cntc](#6,#7)(#8,#9)% \DefPlotSymbol{$\bullet$} \lbezier[1](#2,#3)(#2,#3) \lbezier[1](#4,#5)(#4,#5) \lbezier[1](#6,#7)(#6,#7) \lbezier[1](#8,#9)(#8,#9) \DefStandardPlotSymbol \thinlines} %% % \end{macrocode} % % \verb+\l@put+ is like \verb+\put+ but its arguments are lengths and not % decimal constants. It will be used in \verb+\l@cbezier+ which also has % lengths as arguments. All complex plotting commands use this form. % Just for the calculation of plotting points four more lengths are needed. % I use the ``scratch'' dimens from \TeX. % % \begin{macrocode} \long\gdef\l@put(#1,#2)#3{% \@killglue\raise#2\hb@xt@\z@{\kern#1#3\hss}\ignorespaces} %% \long\gdef\l@cbezier[#1](#2,#3)(#4,#5)(#6,#7)(#8,#9){% \c@@cntc#1\relax \dimen1#2\dimen3#3 %% \@Xa #4 \advance\@Xa-#2 \multiply\@Xa\thr@@ \@Xb #6 \advance\@Xb-#2 \multiply\@Xb\thr@@ \advance\@Xb-2\@Xa \@Xc #8 \advance\@Xc-#2 \advance\@Xc-\@Xa \advance\@Xc-\@Xb \@Ya #5 \advance\@Ya-#3 \multiply\@Ya\thr@@ \@Yb #7 \advance\@Yb-#3 \multiply\@Yb\thr@@ \advance\@Yb-2\@Ya \@Yc #9 \advance\@Yc-#3 \advance\@Yc-\@Ya \advance\@Yc-\@Yb %% %% assume half arc %% \ifnum \c@@cntc <\@ne \multiply\eps\x@ \dimen5#2 \advance\dimen5-#8 \AbsLen{\dimen5}% \dimen7#3 \advance\dimen7-#9 \AbsLen{\dimen7}% \LenNorm{\dimen5}{\dimen7}{\PathLength}% \divide\eps\x@ \c@@cntc\PathLength \dimen5.5\@halfwidth \divide\c@@cntc\dimen5 %% %% 11/7 \approx \pi/2 %% \divide\c@@cntc 7 \multiply\c@@cntc 11 \ifnum \c@@cntc>\qbeziermax \PackageInfo{ebezier}{\the\c@@cntc\space points needed exceeding % qbeziermax=\qbeziermax!}\fi \fi \ifnum\c@@cntc>\qbeziermax \c@@cntc\qbeziermax\relax \PackageWarning{ebezier}{Counter reset to qbeziermax=\qbeziermax!}\fi \c@@cnta\c@@cntc\relax\advance\c@@cnta\@ne% \divide\@Xc\c@@cntc \divide\@Yc\c@@cntc \c@@cntb\z@\relax \set@width \l@put(\dimen1,\dimen3){\@whilenum{\c@@cntb<\c@@cnta}\do {\@X\c@@cntb \@Xc\@Y \c@@cntb\@Yc \advance\@X\@Xb \advance\@Y\@Yb \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \advance\@X\@Xa \advance\@Y\@Ya \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \raise\@Y\hbox to\z@{\hskip\@X\unhcopy\@pt\hss}% \advance\c@@cntb\@ne}}} %% % \end{macrocode} % % The building blocks for the circles are the four quarters. Each is defined % separately and will be combined by the \verb+\cCircle+ macro. % % \begin{macrocode} \def\@circle@rt[#1](#2,#3)#4{% \set@magic \@Z #4\magicnum\@Za #2\unitlength\@Zb #3\unitlength \@Zc #2\unitlength \advance\@Zc\@Z \@Zd #3\unitlength \advance\@Zd\@Z \@Ze #4\unitlength \advance\@Ze\@Za \@Zf #4\unitlength \advance\@Zf\@Zb \l@cbezier[#1](\@Ze,\@Zb)(\@Ze,\@Zd)(\@Zc,\@Zf)(\@Za,\@Zf)} %% \def\@circle@lt[#1](#2,#3)#4{% \set@magic \@Z #4\magicnum\@Za #2\unitlength\@Zb #3\unitlength \@Zc #2\unitlength \advance\@Zc-\@Z \@Zd #3\unitlength \advance\@Zd\@Z \@Ze -#4\unitlength \advance\@Ze\@Za \@Zf #4\unitlength \advance\@Zf\@Zb \l@cbezier[#1](\@Za,\@Zf)(\@Zc,\@Zf)(\@Ze,\@Zd)(\@Ze,\@Zb)} %% \def\@circle@rb[#1](#2,#3)#4{% \set@magic \@Z #4\magicnum\@Za #2\unitlength\@Zb #3\unitlength \@Zc #2\unitlength \advance\@Zc\@Z \@Zd #3\unitlength \advance\@Zd-\@Z \@Ze #4\unitlength \advance\@Ze\@Za \@Zf -#4\unitlength \advance\@Zf\@Zb \l@cbezier[#1](\@Za,\@Zf)(\@Zc,\@Zf)(\@Ze,\@Zd)(\@Ze,\@Zb)} %% \def\@circle@lb[#1](#2,#3)#4{% \set@magic \@Z #4\magicnum\@Za #2\unitlength\@Zb #3\unitlength \@Zc #2\unitlength \advance\@Zc-\@Z \@Zd #3\unitlength \advance\@Zd-\@Z \@Ze -#4\unitlength \advance\@Ze\@Za \@Zf -#4\unitlength \advance\@Zf\@Zb \l@cbezier[#1](\@Ze,\@Zb)(\@Ze,\@Zd)(\@Zc,\@Zf)(\@Za,\@Zf)} %% % \end{macrocode} % % I use the logicals from the \verb+\oval+ defined in \LaTeX. So I need just % one more logical \verb+\if@ovf+. % % \begin{macrocode} \newif\if@ovf \def\cCircle{\@ifnextchar [{\@cCircle}{\@cCircle[0]}} \def\@cCircle[#1](#2,#3)#4[#5]{% \@ovtfalse\@ovbfalse\@ovlfalse\@ovrfalse\@ovffalse \c@@cnta#1\relax \@tfor\reserved@a:=#5\do{\csname @ov\reserved@a true\endcsname}% \if@ovf\@ovttrue \divide\c@@cnta\tw@\fi \if@ovt \if@ovr \@circle@rt[\c@@cnta](#2,#3){#4} \else\if@ovl \@circle@lt[\c@@cnta](#2,#3){#4} \else\divide\c@@cnta\tw@ \@circle@rt[\c@@cnta](#2,#3){#4} \@circle@lt[\c@@cnta](#2,#3){#4} \fi\fi \if@ovf \@circle@rb[\c@@cnta](#2,#3){#4} \@circle@lb[\c@@cnta](#2,#3){#4} \fi \else\if@ovb \if@ovr \@circle@rb[\c@@cnta](#2,#3){#4} \else\if@ovl \@circle@lb[\c@@cnta](#2,#3){#4} \else\divide\c@@cnta\tw@ \@circle@rb[\c@@cnta](#2,#3){#4} \@circle@lb[\c@@cnta](#2,#3){#4} \fi\fi \else \divide\c@@cnta\tw@ \if@ovr \@circle@rb[\c@@cnta](#2,#3){#4} \@circle@rt[\c@@cnta](#2,#3){#4} \else \if@ovl \@circle@lb[\c@@cnta](#2,#3){#4} \@circle@lt[\c@@cnta](#2,#3){#4} \else \PackageError{Ebezier}{Missing or illegal position specifier in cCircle} \fi\fi\fi\fi} %% \def\cArc{\@ifnextchar [{\@cArc}{\@cArc[0]}} \def\@cArc[#1](#2,#3)(#4,#5){% \c@@cntc#1\relax \@X #2\unitlength \@Y #3\unitlength \@Za #4\unitlength \@Zb #5\unitlength \@Zc 2\@X \advance\@Zc-\@Za \@Zd 2\@Y \advance\@Zd-\@Zb \@Xa\@Y \advance\@Xa-\@Zb \@Ya\@Za \advance\@Ya-\@X \multiply\@Xa 4 \divide\@Xa\thr@@ \multiply\@Ya 4 \divide\@Ya\thr@@ \@Ze\@Za \advance\@Ze\@Xa \@Zf\@Zb \advance\@Zf\@Ya \@Zg\@Zc \advance\@Zg\@Xa \@Zh\@Zd \advance\@Zh\@Ya \l@cbezier[#1](\@Za,\@Zb)(\@Ze,\@Zf)(\@Zg,\@Zh)(\@Zc,\@Zd)} %% % \end{macrocode} % % Historically from this point starts the calculation part. The notation % will be more \LaTeX\ convenient. % % All square roots are calculated by the same iteration. To keep numbers % small enough some scaling has to be done (factor \verb+\c@@cntd+). % % \begin{macrocode} \def\LenMult#1#2#3{\setlength{#3}{#1*\ratio{#2}{\unitlength}}} %% \def\LenDiv#1#2#3{\setlength{#3}{\unitlength*\ratio{#1}{#2}}} %% \def\AbsLen#1{\ifdim#1<\z@\setlength{#1}{-#1}\fi} %% \def\LenSqrt#1#2{% \setlength{\@Za}{#1}% \ifdim\@Za>\eps\loop\setlength{\@Zb}{(\@Za+\unitlength*\ratio{#1}{\@Za})/2}% \setlength{\@Zc}{\@Za-\@Zb}\AbsLen{\@Zc}% \ifdim\@Zc>\eps\setlength{\@Za}{\@Zb}\repeat\fi% \setlength{#2}{\@Za}} %% \def\Length(#1,#2)(#3,#4)#5{% \setlength{\@Zd}{#3\unitlength-#1\unitlength}% \setlength{\@Ze}{#4\unitlength-#2\unitlength}% \setcounter{@cntd}{1}% \setlength{\@Zf}{\@Zd}\ifdim\@Ze>\@Zd\setlength{\@Zf}{\@Ze}\fi \loop\setlength{\@Zd}{\@Zd/2}\setlength{\@Ze}{\@Ze/2}\setlength{\@Zf}{\@Zf/2}% \multiply\c@@cntd\tw@\ifdim\@Zf>\x@ pt\repeat \LenMult{\@Zd}{\@Zd}{\@Zg}\LenMult{\@Ze}{\@Ze}{\@Zh}\setlength{\@Zf}{\@Zg+\@Zh}% \LenSqrt{\@Zf}{\@Zg}\setlength{#5}{\@Zg*\value{@cntd}}} %% \def\LenNorm#1#2#3{% \setlength{\@Zd}{#1}\setlength{\@Ze}{#2}\setcounter{@cntd}{1}% \setlength{\@Zf}{\@Zd}\ifdim\@Ze>\@Zd\setlength{\@Zf}{\@Ze}\fi \loop\setlength{\@Zd}{\@Zd/2}\setlength{\@Ze}{\@Ze/2}\setlength{\@Zf}{\@Zf/2}% \multiply\c@@cntd\tw@\ifdim\@Zf>\x@ pt\repeat \LenMult{\@Zd}{\@Zd}{\@Zg}\LenMult{\@Ze}{\@Ze}{\@Zh}\setlength{\@Zf}{\@Zg+\@Zh}% \LenSqrt{\@Zf}{\@Zg}\setlength{#3}{\@Zg*\value{@cntd}}} %% \def\PathLengthQ[#1](#2,#3)(#4,#5)(#6,#7){% \PathLength\z@\c@@cntc#1\relax \ifnum \c@@cntc<\@ne \c@@cntc\pathmax\relax\fi \ifnum \c@@cntc>\pathmax \c@@cntc\pathmax\relax \PackageWarning{ebezier}{Counter reset to pathmax=\pathmax!}\fi \@Za\z@ \@Zb\z@ \c@@cntb\c@@cntc\relax \advance\c@@cntb\@ne \@Xb #4\unitlength \advance\@Xb-#2\unitlength \multiply\@Xb\tw@ \@Yb #5\unitlength \advance\@Yb-#3\unitlength \multiply\@Yb\tw@ \@Xa #6\unitlength \advance\@Xa-#2\unitlength \advance\@Xa-\@Xb \divide\@Xa\c@@cntc \@Ya #7\unitlength \advance\@Ya-#3\unitlength \advance\@Ya-\@Yb \divide\@Ya\c@@cntc \c@@cnta\@ne\relax \@whilenum{\c@@cnta<\c@@cntb}\do {\@X\c@@cnta\@Xa \advance\@X\@Xb \divide\@X\c@@cntc \multiply\@X\c@@cnta \@Y\c@@cnta\@Ya \advance\@Y\@Yb \divide\@Y\c@@cntc \multiply\@Y\c@@cnta \@Zi\@X\@Zj\@Y \advance\@X-\@Za \advance\@Y-\@Zb \LenNorm{\@X}{\@Y}{\@Z}% \advance\PathLength\@Z \@Za\@Zi\@Zb\@Zj \advance\c@@cnta\@ne}} %% \def\PathLengthC[#1](#2,#3)(#4,#5)(#6,#7)(#8,#9){% \PathLength\z@ \c@@cntc#1\relax \ifnum \c@@cntc<\@ne \c@@cntc\pathmax\relax\fi \ifnum \c@@cntc>\pathmax \c@@cntc\pathmax\relax \PackageWarning{ebezier}{Counter reset to pathmax=\pathmax!}\fi \@Za\z@ \@Zb\z@ \c@@cnta\c@@cntc\relax \advance\c@@cnta\@ne \@Xa #4\unitlength \advance\@Xa-#2\unitlength \multiply\@Xa\thr@@ \@Xb #6\unitlength \advance\@Xb-#2\unitlength \multiply\@Xb\thr@@ \advance\@Xb-2\@Xa \@Xc #8\unitlength \advance\@Xc-#2\unitlength \advance\@Xc-\@Xa \advance\@Xc-\@Xb \@Ya #5\unitlength \advance\@Ya-#3\unitlength \multiply\@Ya\thr@@ \@Yb #7\unitlength \advance\@Yb-#3\unitlength \multiply\@Yb\thr@@ \advance\@Yb-2\@Ya \@Yc #9\unitlength \advance\@Yc-#3\unitlength \advance\@Yc-\@Ya \advance\@Yc-\@Yb \divide\@Xc\c@@cntc \divide\@Yc\c@@cntc \c@@cntb\@ne\relax \@whilenum{\c@@cntb<\c@@cnta}\do {\@X\c@@cntb\@Xc \@Y\c@@cntb\@Yc \advance\@X\@Xb \advance\@Y\@Yb \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \advance\@X\@Xa \advance\@Y\@Ya \divide\@X\c@@cntc \divide\@Y\c@@cntc \multiply\@X\c@@cntb \multiply\@Y\c@@cntb \@Zi\@X\@Zj\@Y \advance\@X-\@Za \advance\@Y-\@Zb \LenNorm{\@X}{\@Y}{\@Z}% \advance\PathLength\@Z \@Za\@Zi\@Zb\@Zj\advance\c@@cntb\@ne}} %% % \end{macrocode} % % The most complex macro is explained in the text. The exception is % handled by the logical \verb+\if@ovf+. % % \begin{macrocode} \def\cArcs{\@ifnextchar [{\@cArcs}{\@cArcs[0]}} \def\@cArcs[#1](#2,#3)(#4,#5)(#6,#7){% \c@@cntc#1\relax \@ovffalse \@X#2\unitlength\@Y#3\unitlength \@Zi#6\unitlength\@Zj#7\unitlength \setlength{\@Xa}{\@X-\@Zi}\setlength{\@Ya}{\@Y-\@Zj}% \LenNorm{\@Xa}{\@Ya}{\@Xb}% \@Xa#4\unitlength \advance\@Xa\@Zi \advance\@Xa-2\@X \@Ya#5\unitlength \advance\@Ya\@Zj \advance\@Ya-2\@Y \@Xc\@Xa\AbsLen{\@Xc}\@Yc\@Ya\AbsLen{\@Yc}% \ifdim\@Xc<\eps\ifdim\@Yc<\eps\@ovftrue\fi\fi \if@ovf \cArc[#1](#2,#3)(#4,#5)% \else \LenNorm{\@Xa}{\@Ya}{\@Yb}% \setlength{\@Xc}{\unitlength*\ratio{\@Xb}{\@Yb}}% \setlength{\@Yc}{(-\unitlength+\@Xc*2)*4/3}% \@Xb-#5\unitlength \advance\@Xb\@Zj \@Z\@Xb\AbsLen{\@Z}% \ifdim\@Z<100\eps \@Xb#4\unitlength \advance\@Xb-\@Zi \@Xa\@Ya\fi \setlength{\@Z}{\@Yc*\ratio{\@Xa}{\@Xb}}% \@Xa#4\unitlength\@Ya#5\unitlength \setlength{\@Za}{\@Y-\@Ya}\setlength{\@Zb}{\@Xa-\@X}% \setlength{\@Zc}{\@Zj-\@Y}\setlength{\@Zd}{\@X-\@Zi}% \@Xb\@Xa \LenMult{\@Z}{\@Za}{\@Zh}\advance\@Xb\@Zh \@Yb\@Ya\LenMult{\@Z}{\@Zb}{\@Zh}\advance\@Yb\@Zh \@Xc\@Zi\LenMult{\@Z}{\@Zc}{\@Zh}\advance\@Xc\@Zh \@Yc\@Zj\LenMult{\@Z}{\@Zd}{\@Zh}\advance\@Yc\@Zh \@Z\@Xa\@Za\@Ya\@Zb\@Xb\@Zc\@Yb\@Zd\@Xc\@Ze\@Yc \l@cbezier[#1](\@Z,\@Za)(\@Zb,\@Zc)(\@Zd,\@Ze)(\@Zi,\@Zj)% \fi} % % \end{macrocode} % \Finale \PrintIndex \PrintChanges \endinput