From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/curve2e/README.txt | 108 + macros/latex/contrib/curve2e/curve2e.dtx | 4591 ++++++++++++++++++++++++++++++ macros/latex/contrib/curve2e/curve2e.pdf | Bin 0 -> 513014 bytes macros/latex/contrib/curve2e/ltxdoc.cfg | 7 + 4 files changed, 4706 insertions(+) create mode 100644 macros/latex/contrib/curve2e/README.txt create mode 100644 macros/latex/contrib/curve2e/curve2e.dtx create mode 100644 macros/latex/contrib/curve2e/curve2e.pdf create mode 100644 macros/latex/contrib/curve2e/ltxdoc.cfg (limited to 'macros/latex/contrib/curve2e') diff --git a/macros/latex/contrib/curve2e/README.txt b/macros/latex/contrib/curve2e/README.txt new file mode 100644 index 0000000000..63631d80e6 --- /dev/null +++ b/macros/latex/contrib/curve2e/README.txt @@ -0,0 +1,108 @@ +%% +%% This is file `README.txt', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% curve2e.dtx (with options: `readme') +%% +%% Copyright (C) 2005--2019 Claudio Beccari all rights reserved. +%% License information appended +%% +File README.txt for package curve2e + [2019-03-29 v.2.0.1 Extension package for pict2e] + + + +The package bundle curve2e is composed of the following files + +curve2e.dtx +curve2e.pdf +README.txt +curve2e-v161.sty +ltxdoc.cfg + +curve2e.dtx is the documented TeX source file of file curve2e.sty; you get +both curve2e.sty and curve2e.pdf by running pdflatex on curve2e.dtx. +The ltxdoc.cfg file customises the way the documentation file is typeset. +This .cfg file is not subject to the LPPL licence. + +README.txt, this file, contains general information. + +Curve2e-v161.sty contains the previous version of the package; see below +why the older version might become necessary for the end user. + +Curve2e.sty is an extension of the package pict2e.sty which extends the +standard picture LaTeX environment according to what Leslie Lamport +specified in the second edition of his LaTeX manual. + +This further extension allows to draw lines and vectors with any non +integer slope parameters, to draw dashed lined of any slope, to draw arcs +and curved vectors, to draw curves where just the interpolating nodes are +specified together with the slopes at the nodes; closed paths of any shape +can be filled with color; all coordinates are treated as ordered pairs, +i.e. 'complex numbers'; coordinates may be expressed also in polar form. +Some of these features have been incorporated in the 2011 version of +pict2e; therefore this package avoids any modification to the original +pict2e commands. + +Curve2e now accepts polar coordinates in addition to the usual cartesian +ones; several macros have been upgraded and a new macro for tracing cubic +Bezier splines with their control nodes specified in polar form is available. The same applies to quadratic Bezier splines. + +This version solves a conflict with package eso-pic. + +This version of curve2e is almost fully compatible with pict2e dated +2014/01/12 version 0.2z. + +If you specify + +\usepackage[]{curve2e} + +the package pict2e is automatically invoked with the specified options. + +The -almost compatible- frase is necessary to explain that this version +of curve2e uses some `functions' of the LaTeX3 language that were made +available to the LaTeX developer by mid October 2018. Should the user +have an older or a basic/incomplete installation of the TeX system, +such L3 functions might not be available. This is why this +package checks the presence of the developer interface; in case +such interface is not available it falls back to the previous version +renamed curve2e-v161.sty, which is part of this bundle, and that must +not be renamed in any way. The compatibility mentioned above implies +that the user macros remain the same, but their implementation requires +the L3 interface. + +The package has the LPPL status of author maintained. + +According to the LPPL licence, you are entitled to modify this package, +as long as you fulfil the few conditions set forth by the Licence. + +Nevertheless this package is an extension to the standard LaTeX package +pict2e (2014). Therefore any change must be controlled on the +parent package pict2e, so as to avoid redefining what has already been +incorporated in the official package. + +If you prefer sending me your modifications, as long as I will maintain +this package, I will possibly include every (documented) suggestion or +modification into this package and, of course, I will acknowledge your +contribution. + +Claudio Beccari + +claudio dot beccari at gmail dot com + +%% +%% +%% Distributable under the LaTeX Project Public License, +%% version 1.3c or higher (your choice). The latest version of +%% this license is at: http://www.latex-project.org/lppl.txt +%% +%% This work is "author-maintained" +%% +%% This work consists of file curve2e.dtx, and the derived files +%% curve2e.sty and curve2e.pdf, plus the auxiliary derived files +%% README.txt and manifest.txt. +%% +%% +%% End of file `README.txt'. diff --git a/macros/latex/contrib/curve2e/curve2e.dtx b/macros/latex/contrib/curve2e/curve2e.dtx new file mode 100644 index 0000000000..902cd4e1a6 --- /dev/null +++ b/macros/latex/contrib/curve2e/curve2e.dtx @@ -0,0 +1,4591 @@ +% \iffalse +% !TEX encoding = UTF-8 Unicode +%<*internal> +\begingroup +\input docstrip.tex +\keepsilent +\preamble + + Copyright (C) 2005--2019 Claudio Beccari all rights reserved. + License information appended + +\endpreamble + +\postamble + + +Distributable under the LaTeX Project Public License, +version 1.3c or higher (your choice). The latest version of +this license is at: http://www.latex-project.org/lppl.txt + +This work is "author-maintained" + +This work consists of file curve2e.dtx, and the derived files +curve2e.sty and curve2e.pdf, plus the auxiliary derived files +README.txt and manifest.txt. + +\endpostamble +\askforoverwritefalse + +\generate{\file{curve2e.sty}{\from{curve2e.dtx}{package}}} +\generate{\file{README.txt}{\from{curve2e.dtx}{readme}}} +\generate{\file{curve2e-v161.sty}{\from{curve2e.dtx}{v161}}} + +\def\tmpa{plain} +\ifx\tmpa\fmtname\endgroup\expandafter\bye\fi +\endgroup +% +% \fi +% +% \iffalse +%<*package> +%\NeedsTeXFormat{LaTeX2e}[2016/01/01] +% +%<*driver> +\ProvidesFile{curve2e.dtx}% +% +%<+package>\ProvidesPackage{curve2e}% +%<+readme>File README.txt for package curve2e +%<*package|readme> + [2019-03-29 v.2.0.1 Extension package for pict2e] +% +%<*driver> +\documentclass{ltxdoc}\errorcontextlines=9 +\hfuzz 10pt +\usepackage[utf8]{inputenc} +\usepackage{lmodern,textcomp} +\usepackage{mflogo} +\usepackage{multicol,amsmath,fancyvrb,trace} +\usepackage{curve2e} +\GetFileInfo{curve2e.dtx} +\title{The extension package \textsf{curve2e}} +\author{Claudio Beccari\thanks{E-mail: \texttt{claudio dot beccari at gmai dot com}}} +\date{Version \fileversion~--~Last revised \filedate.} +\providecommand*\diff{\mathop{}\!\mathrm{d}} +\renewcommand\meta[1]{{\normalfont\textlangle\textit{#1}\textrangle}} +\renewcommand\marg[1]{\texttt{\char123\meta{#1}\char125}} +\providecommand\oarg{} +\renewcommand\oarg[1]{\texttt{[\meta{#1}]}} +\providecommand\aarg{} +\renewcommand*\aarg[1]{\texttt{<\meta{#1}>}} +\providecommand\parg{} +\renewcommand\parg[1]{\texttt{(\meta{#1})}} +\makeatletter + +\newcommand*\Pall[1][1.5]{\def\circdiam{#1}\@Pall} + \def\@Pall(#1){\put(#1){\circle*{\circdiam}}} + +\def\legenda(#1)#2{\put(#1){\setbox3333\hbox{$#2$}% + \dimen3333\dimexpr\wd3333*\p@/\unitlength +3\p@\relax + \edef\@tempA{\strip@pt\dimen3333}% + \framebox(\@tempA,7){\box3333}}} + +\def\Zbox(#1){\bgroup\edef\@tempA{#1}\@Zbox} + +\newcommand*\@Zbox[2][]{\fboxrule\z@\fboxsep=0.75ex\def\@tempB{#1}% +\setbox2575\hbox{\fbox{$\relax\rule[-0.5ex]{0pt}{2.5ex}#2\relax$}}\relax +\ifx\@tempB\empty +\put(\@tempA){\makebox(0,0){\box2575}}\else +\put(\@tempA){\makebox(0,0)[#1]{\box2575}}\fi\egroup\ignorespaces} + +\providecommand\setfontsize{} +\DeclareRobustCommand\setfontsize[2][1.2]{% +\linespread{#1}\fontsize{#2}{#2}\selectfont} + + +\begin{document}%\OnlyDescription +\maketitle +\columnseprule=0.4pt +\begin{multicols}{2} + \tableofcontents + \end{multicols} + \DocInput{curve2e.dtx} +\end{document} +% +% \fi +% +% \CheckSum{5560} +% \begin{abstract} +% This file documents the |curve2e| extension package to the |pict2e| +% bundle implementation that has been described by Lamport +% himself in the 1994 second edition of his \LaTeX\ handbook. +% +% Please take notice that in April 2011 a new updated version of the +% package |pict2e| has been released that incorporates some of the +% commands defined in early versions of this package; apparently there +% are no conflicts, but only the advanced features of |curve2e| remain +% available for extending the above package. +% +% This extension redefines a couple of commands and introduces some more +% drawing facilities that allow to draw circular arcs and arbitrary curves +% with the minimum of user intervention. This version is open to the +% contribution of other users as well as it may be incorporated in other +% people's packages. Please cite the original author and the chain of +% contributors. +% \end{abstract} +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%\section{The configuration file} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This package |curve2e| is distributed with a |ltxdoc.cfg| configuration +% file that contains, besides the preamble and the postamble comment lines, +% the following code line: +%\begin{verbatim} +%\AtBeginDocument{\OnlyDescription} +%\end{verbatim} +% +% If you want to type the whole documentation, comment out that code line +% in the |ltxdoc.cfg| file. This is the only modification allowed by the +% LPPL licence that does not require to change the file name. +% +% For your information the initial part is about 20~pages long; the whole +% documentation is about 80~pages long. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Package \texttt{pict2e} and this extension \texttt{curve2e}} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Package \texttt{pict2e} was announced in issue 15 of \texttt{latexnews} +% around December 2003; it was declared that the new package would replace +% the dummy one that has been accompanying every release of \LaTeXe\ since +% its beginnings in 1994. The dummy package was just issuing an info +% message that simply announced the temporary unavailability of the real +% package. +% +% Eventually Gäßlein and Niepraschk implemented what Lamport himself had +% already documented in the second edition of his \LaTeX\ handbook, that is +% a \LaTeX\ package that contained the macros capable of removing all the +% limitations contained in the standard commands of the original +% \texttt{picture} environment; specifically what follows. +% \begin{enumerate} +% \item The line and vector slopes were limited to the ratios of relative +% prime one-digit integers of magnitude not exceeding 6 for lines and 4 for +% vectors. +%^^A +% \item Filled and unfilled full circles were limited by the necessarily +% limited number of specific glyphs contained in the special \LaTeX\ +% \texttt{picture} fonts. +%^^A +% \item Quarter circles were also limited in their radii for the same +% reason. +%^^A +% \item Ovals (rectangles with rounded corners) could not be too small +% because of the unavailability of small radius quarter circles, nor could +% be too large, in the sense that after a certain radius the rounded +% corners remained the same and would not increase proportionally to the +% oval size. +%^^A +% \item Vector arrows had only one possible shape and matched the limited +% number of vector slopes. +%^^A +% \item For circles and inclined lines and vectors just two possible +% thicknesses were available. +% \end{enumerate} +% +% The package \texttt{pict2e} removes most if not all the above +% limitations. +% \begin{enumerate} +% \item Line and vector slopes are virtually unlimited; the only remaining +% limitation is that the direction coefficients must be three-digit integer +% numbers; they need not be relatively prime; with the 2009 upgrade even +% this limitation was removed and now slope coefficients can be any +% fractional number whose magnitude does not exceed 16\,384, the maximum +% dimension in points that \TeX\ can handle. +%^^A +% \item Filled and unfilled circles can be of any size. +%^^A +% \item Ovals can be designed with any specified corner curvature and there +% is virtually no limitation to such curvatures; of course corner radii +% should not exceed half the lower value between the base and the height of +% the oval. +%^^A +% \item There are two shapes for the arrow tips; the triangular one +% traditional with \LaTeX\ vectors, or the arrow tip with PostScript style. +%^^A +% \item The |\linethickness| command changes the thickness of all lines, +% straight, curved, vertical, horizontal, arrow tipped, et cetera. +% \end{enumerate} +% +% This specific extension package |curve2e| adds the following features. +% \begin{enumerate} +% \item Point coordinates my be specified in both cartesian and polar form: +% internally they are handeld as cartesian coordinates, but the user can +% specify his/her points also in polar form. In order to avoid confusion +% with other grapgic packages, |curve2e| uses the usual comma separated +% couple of integer or fractional numebrs for cartesian coordinates, and +% the couple \texttt{\meta{angle}:\meta{radius}} for polar coordinates. +% All graphic object commands accept polar or cartesian coordinates at the +% choice of the user who may use for each object the formalism he/she +% prefers. Also the |put| and |\multiput| commands have been redefined so +% as to accept cartesian or polar coordinates. +%^^A +%\item Most if not all cartesian coordinate pairs and slope pairs are +% treated as \emph{ordered pairs}, that is \emph{complex numbers}; in +% practice the user does not notice any difference from what he/she was +% used to, but all the mathematical treatment to be applied to these +% entities is coded as complex number operations, since complex numbers may +% be viewed non only as ordered pairs, but also as vectors or as +% roto-amplification operators. +%^^A +% \item Commands for setting the line terminations are introduced; the user +% can chose between square or rounded caps; the default is set to rounded +% caps (now this original feature is directly available also with +% |pict2e|). +%^^A +% \item Commands for specifying the way two lines or curves join to one +% another. +% ^^A +% \item originally the |\line| macro is redefined so as to allow integer +% and fractional direction coefficients, but maintaining the same syntax as +% in the original \texttt{picture} environment; now this functionality +% available directly with |pict2e|. +% ^^A +% \item A new macro |\Line| was originally defined so as to avoid the need +% to specify the horizontal projection of inclined lines; now this +% functionality id available directly with |pict2e|; but this macro name +% now conflicts with |pict2e| 2009 version; therefore its name is changed +% to |\LIne| and supposedly it will not be used very often, if ever, +% by the end user (but it is used within this package macros). +% ^^A +% \item A new macro |\LINE| was defined in order to join two points +% specified with their coordinates; this is now the normal behavior of the +% |\Line| macro of |pict2e| so that in this package |\LINE| is now renamed +% |\segment|; there is no need to use the |\put| command with this line +% specification. +% ^^A +% \item A new macro |\DLine| is defined in order to draw dashed lines +% joining any two given points; the dash length and gap (equal to one another) get specified through one of the macro arguments. +% ^^A +% \item A new macro |\Dotline| is defined in order to draw dotted straight +% lines as a sequence of equally spaced dots, where the gap can be +% specified by the user; such straight line may have any inclination, as +% well as the above dashed lines. +% ^^A +% \item Similar macros are redefined for vectors; |\vector| redefines the +% original macro but with the vector slope limitations removed; |\Vector| +% gets specified with its two horizontal and vertical components in analogy +% with |\LIne|; |\VECTOR| joins two specified points (without using the +% |\put| command) with the arrow pointing to the second point. +%^^A +% \item A new macro |\polyline| for drawing polygonal lines is defined that +% accepts from two vertices up to an arbitrary (reasonably limited) number +% of them (available now also in |pict2e|); here it is redefined so as to +% allow an optional specification of the way segments for the polyline are +% joined to one another. Vertices may be specified with polar coordinates +%^^A +% \item The |pict2e| |polygon| macro to draw closed polylines, in practice +% general polygons, has been redefined in such a way that it can accept the +% various vertices specified with polar coordinates. The |polygon*| macro +% produces a color filled polygon; the default color is black, but a +% different color may be specified with the usual |\color| command given +% within the same group where |\polygon*| is enclosed. +%^^A +% \item A new macro |\Arc| is defined in order to draw an arc with +% arbitrary radius and arbitrary aperture (angle amplitude); this amplitude +% is specified in sexagesimal degrees, not in radians; a similar +% functionality is now achieved with the |\arc| macro of |pict2e|, which +% provides also the starred version |\arc*| that fills up the interior of +% the generated circular arc with the current color. It must be noticed +% that the syntax is slightly different, so that it's reasonable that these +% commands, in spite of producing identical arcs, might be more comfortable +% with this or that syntax. +%^^A +% \item Two new macros |\VectorArc| and |\VectorARC| are defined in order +% to draw circular arcs with an arrow at one or both ends. +%^^A +% \item A new macro |\Curve| is defined so as to draw arbitrary curved +% lines by means of cubic Bézier splines; the |\Curve| macro requires only +% the curve nodes and the directions of the tangents at each node.The +% starred version fills up the interior of the curve with the current +% color. +%^^A +% \item |\Curve| is a recursive macro that can draw an unlimited +% (reasonably limited) number of connected Bézier spline arcs with +% continuous tangents except for cusps; these arcs require only the +% specification of the tangent direction at the interpolation nodes. It is +% possible to use a lower level macro |\CbezierTo| that does the same but +% lets the user specify the control points of each arc; it is more +% difficult to use but it is more performant. +%^^A +% \item The basic macros used within the cumulative |\Curve| macro can be +% used individually in order to draw any curve, one cubic arc at the time; +% but they are intended for internal use, even if it is not prohibited to +% use them; by themselves such arcs are not different form those used by +% |Curve|, but the final command, |\FillCurve|, should be used in place of +% |\CurveFinish|, so as to fill up the closed path with the locally +% specified color; see figure~\ref{fig:colored-curve}. It is much more +% convenient to use the starred version of the |\Curve| macro. +% \end{enumerate} +% +% The |pict2e| package already defines macros such as |\moveto|, |\lineto|, +% |\curveto|, |\closepath|, |\fillpath|, and |\strokepath|; of course these +% macros can be used by the end user, and sometimes they perform better +% than the macros defined in this package, because the user has a better +% control on the position of the Bézier control points, while here the +% control points are sort of rigid. It would be very useful to resort to +% the |hobby| package, but its macros are conforming with those of the +% |tikz| and |pgf| packages, not with |curve2e|; an interface should be +% created in order to deal with the |hobby| package, but this has not been +% done yet. +% +% In order to make the necessary calculations many macros have been defined +% so as to use complex number arithmetics to manipulate point coordinates, +% directions (unit vectors, also known as `versors'), rotations and the +% like. In the first versions of this package the trigonometric functions +% were also been defined in a way that the author believed to be more +% efficient than those defined by the \texttt{trig} package; in any case +% the macro names were sufficiently different to accommodate both +% definition sets in the same \LaTeX\ run. With the progress of the +% \LaTeX\,3 language, the |xfp| has recently become available, by which any +% sort of calculations can be done with floating point numbers; therefore +% the most common algebraic, irrational and transcendental functions can +% be computed in the background with the stable internal floating point +% facilities. We maintain some computation with complex number algebra, +% but use the |xfp| functionalities for other computations. +% +% Many aspects of this extension could be fine tuned for better +% performance; many new commands could be defined in order to further +% extend this extension. If the new service macros are accepted by other +% \TeX\ and \LaTeX\ programmers, this version could become the start for a +% real extension of the \texttt{pict2e} package or even become a part of +% it. Actually some macros have already been included in the +% \texttt{pict2e} package. The |\Curve| algorithm, as I said before, might +% be redefined so as to use the macros introduced in the \texttt{hobby} +% package, that implements for the |tikz| and |pgf| packages the same +% functionalities that John Hobby implemented for the \MF\ and \MP\ +% programs. +% +% For these reasons I suppose that every enhancement should be submitted to +% Gäßlein, Niepraschk, and Tkadlec who are the prime maintainers of +% \texttt{pict2e}; they are the only ones who can decide whether or not to +% incorporate new macros in their package. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Summary and examples of new commands} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% This package \texttt{curve2e} extends the power of \texttt{pict2e} with +% the following modifications and the following new commands. +% \begin{enumerate} +% \item This package |curve2e| calls directly the \LaTeX\ packages |color| +% and |pict2e| to which it passes any possible option that the latter can +% receive; actually the only options that make sense are those concerning +% the arrow tips, either \LaTeX\ or PostScript styled, because it is +% assumed that if you use this package you are not interested in using the +% original \LaTeX\ commands. See the |pict2e| documentation in order to see +% the correct options |pict2e| can receive. +%^^A +% \item The user is offered new commands in order to control the line +% terminators and the line joins; specifically: +% \begin{itemize} +% \item |\roundcap|: the line is terminated with a semicircle; +% \item |\squarecap|: the line is terminated with a half square; +% \item |\roundjoin|: two lines are joined with a rounded join; +% \item |\beveljoin|: two lines are joined with a bevel join; +% \item |\miterjoin|: two lines are joined with a miter join. +% \end{itemize} +% All the above commands should respect the intended range; but since they +% act at the PostScript or PDF level, not at \TeX\ level, it might be +% necessary to issue the necessary command in order to restore the previous +% terminator or join. +%^^A +% \item The commands |\linethickness|, |\thicklines|, |\thinlines| together +% with |\defaultlinethickness| always redefine the internal |\@wholewidth| +% and |\@halfwidth| so that the latter always refer to a full width and to +% a half of it in this way: if you issue the command +% |\defaultlinewidth{2pt}| all thin lines will be drawn with a thickness +% of 1\,pt while, if a drawing command directly refers to the internal +% value |\@wholewidth|, its line will be drawn with a thickness of 2\,pt. +% If one issues the declaration |\thinlines| all lines will be drawn with +% a 1\,pt width, but if a command refers to the internal value +% |\@halfwidth| the line will be drawn with a thickness of 0.5\,pt. The +% command |\linethickness| redefines the above internals but does not +% change the default width value; all these width specifications apply to +% all lines, straight ones, curved ones, circles, ovals, vectors, dashed, +% et cetera. It's better to recall that |\thinlines| and |\thicklines| are +% declarations that do not take arguments; on the opposite the other two +% commands follow the standard syntax: +% \begin{flushleft} +% |\linethickness|\marg{dimensioned value}\\ +% |\defaultlinewidth|\marg{dimensioned value} +% \end{flushleft} +% where \meta{dimensioned value} means a length specification complete of +% its units or a dimensional expression. +%^^A +% \item Straight lines and vectors are redefined in such a way that +% fractional slope coefficients may be specified; the zero length line does +% not produce errors and is ignored; the zero length vectors draw only the +% arrow tips. +%^^A +% \item New line and vector macros are defined that avoid the necessity of +% specifying the horizontal component; |\put(3,4){\LIne(25,15)}| specifies +% a segment that starts at point $(3,4)$ and goes to point $(3+25,4+15)$; +% the command |\segment(3,4)(28,19)| achieves the same result without the +% need of using command |\put|. +% The same applies to the vector commands |\Vector| and |\VECTOR| and +% |\VVECTOR|; the latter command behaves as |\VECTOR| but draws a vector +% with arrow tips at both ends; furthermore this command is available only with this new release of the |curve2e| package. +% Experience has shown that the commands intended to join two specified +% points are particularly useful. +% \begin{figure} +% \begin{minipage}{.48\textwidth} +% \begin{verbatim} +% \unitlength=.5mm +% \begin{picture}(60,20) +% \put(0,0){\GraphGrid(80,20)} +% \put(0,0){\vector(1.5,2.3){10}} +% \put(20,0){\Vector(10,15.33333)} +% \VECTOR(40,0)(50,15.33333) +% \ifdefined\VVECTOR \VVECTOR(60,0)(80,10)\fi +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\textwidth}\centering +% \unitlength=.5mm +% \begin{picture}(60,20) +% \put(0,0){\GraphGrid(80,20)} +% \put(0,0){\vector(1.5,2.3){10}} +% \put(20,0){\Vector(10,15.33333)} +% \VECTOR(40,0)(50,15.33333) +% \ifdefined\VVECTOR \VVECTOR(60,0)(80,10)\fi +% \end{picture} +% \end{minipage} +% \caption{Three (displaced) identical vectors obtained with the three +% vector macros\ifdefined\VVECTOR; a double tipped vector is also shown\fi.}\label{fig:vectors} +% \end{figure} +%^^A +% \item The |\polyline| command has been introduced: it accepts an +% unlimited list of point coordinates enclosed within round parentheses; +% the command draws a sequence of connected segments that join in order the +% specified points; the syntax is: +% \begin{flushleft} +%\cs{polyline}\oarg{optional join style}\parg{$P_1$}\parg{$P_2$}\texttt{...}\parg{$P_n$} +% \end{flushleft} +% See figure~\ref{fig:polyline} where a regular pentagon is drawn; usage +% of polar coordinates is also shown. +% +% \begin{figure}[!ht] +% \begin{minipage}{.48\linewidth} +% \begin{verbatim} +% \unitlength=.5mm +% \begin{picture}(40,32)(-20,-20) +% \polyline(90:20)(162:20)(234:20)(306:20)(378:20)(90:20) +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\linewidth}\raggedleft +% \unitlength=.5mm +% \begin{picture}(40,32)(-20,-20) +% \polyline(90:20)(162:20)(234:20)(306:20)(378:20)(90:20) +% \end{picture}\hspace*{2em} +% \end{minipage} +% \caption{Polygonal line obtained by means of the \texttt{\string\polyline} +% command; vertex coordinates are in polar form.} +% \label{fig:polyline} +% \end{figure} +% +% Examples of using polar and cartesian coordinates are shown in +% figure~\ref{fig:polar}. +% +%\begin{figure}[htb]\unitlength=0.01\textwidth +%\begin{minipage}{0.55\textwidth} +%\begin{verbatim} +%\begin{picture}(40,30) +%\put(0,0){\GraphGrid(40,30)} +%\put(40,0){\circle*{1.5}} +% \put(41,0){\makebox(0,0)[bl]{40,0}} +%\put(90:30){\circle*{1.5}} +% \put(90:31){\makebox(0,0)[bl]{90:30}} +%\put(60:30){\circle*{1.5}} +% \put(60:31){\makebox(0,0)[bl]{60:30}} +%\put(30,30){\circle*{1.5}} +% \put(30.7,30.7){\makebox(0,0)[bl]{30,30}} +%\multiput(0,0)(30:10){5}% +% {\makebox(0,0){\rule{1.5mm}{1.5mm}}} +%\end{picture} +%\end{verbatim} +%\end{minipage} +%\hfill +%\begin{minipage}{0.4\textwidth} +%\begin{picture}(40,30) +%\put(0,0){\GraphGrid(40,30)} +%\put(40,0){\circle*{1.5}}\put(41,0){\makebox(0,0)[l]{40,0}} +%\put(90:30){\circle*{1.5}}\put(90:31){\makebox(0,0)[bc]{90:30}} +%\put(60:30){\circle*{1.5}}\put(60:3){\Zbox(60:27)[bc]{60{:}30}} +%\put(30,30){\circle*{1.5}}\put(30.7,30.7){\makebox(0,0)[bc]{30,30}} +%\multiput(0,0)(30:10){5}{\makebox(0,0){\rule{1.5mm}{1.5mm}}} +%\end{picture} +%\end{minipage} +%\caption{Use of cartesian and polar coordinates} +%\label{fig:polar} +%\end{figure} +% +% A similar example may be obtained with the |\polygon| macro that does +% not require to terminate the polyline at the starting point. +% Figure~\ref{fig:polygon} shows how to get a coloured filled pentagon. +% +% \begin{figure}[!ht] +% \begin{minipage}{.48\linewidth} +% \begin{verbatim} +% \unitlength=.5mm +% \begin{picture}(40,32)(-20,-20) +% \color{magenta} +% \polygon*(90:20)(162:20)(234:20)(306:20)(378:20) +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\linewidth}\raggedleft +% \unitlength=.5mm +% \begin{picture}(40,32)(-20,-20) +% \color{magenta} +% \polygon*(90:20)(162:20)(234:20)(306:20)(378:20) +% \end{picture}\hspace*{2em} +% \end{minipage} +% \caption{A pentagon obtained by means of the \texttt{\string\polygon*} +% command; vertex coordinates are in polar form.} +% \label{fig:polygon} +% \end{figure} +% +% \item The new command |\Dashline| (alias: |\Dline| for backwards +% compatibility) +% \begin{flushleft} +% |\Dashline|\parg{first point}\parg{second point}\marg{dash length} +% \end{flushleft} +% draws a dashed line containing as many dashes as possible, just as long +% as specified, and separated by a gap exactly the same size; actually, +% in order to make an even gap-dash sequence, the desired dash length is +% used to do some computations in order to find a suitable length, close +% to the one specified, such that the distance of the end points is evenly +% divided in equally sized dashes and gaps. +% The end points may be anywhere in the drawing area, without any +% constraint on the slope of the joining segment. The desired dash length +% is specified as a fractional multiple of |\unitlength|; see +% figure~\ref{fig:dashline}. +% \begin{figure}[!ht] +% \begin{minipage}{.48\textwidth} +% \begin{verbatim} +% \unitlength=1mm +% \begin{picture}(40,40) +% \put(0,0){\GraphGrid(40,40)} +% \Dashline(0,0)(40,10){4} +% \put(0,0){\circle*{2}} +% \Dashline(40,10)(0,25){4} +% \put(40,10){\circle*{2}} +% \Dashline(0,25)(20,40){4} +% \put(0,25){\circle*{2}} +% \put(20,40){\circle*{2}} +% \Dotline(0,0)(40,40){2} +% \put(40,40){\circle*{2}} +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\textwidth}\centering +% \unitlength=1mm +% \begin{picture}(40,40) +% \put(0,0){\GraphGrid(40,40)} +% \Dashline(0,0)(40,10){4} +% \put(0,0){\circle*{2}} +% \Dashline(40,10)(0,25){4} +% \put(40,10){\circle*{2}} +% \Dashline(0,25)(20,40){4} +% \put(0,25){\circle*{2}} +% \put(20,40){\circle*{2}} +% \Dotline(0,0)(40,40){2} +% \put(40,40){\circle*{2}} +% \end{picture} +% \end{minipage} +% \caption{Dashed lines and graph grid}\label{fig:dashline} +% \end{figure} +% Another example of usage of cartesian and polar coordinates usage is +% shown in figure~\ref{fig:polar} together with its code. +% +%\begin{figure}\unitlength=0.007\textwidth +%\begin{minipage}{0.55\textwidth} +%\begin{verbatim} +%\begin{picture}(40,30) +%\put(0,0){\GraphGrid(40,30)} +%\Dashline(0,0)(40,10){2}\Dashline(0,0)(40,20){2} +%\Dashline(0,0)(40,30){2}\Dashline(0,0)(30,30){2} +%\Dashline(0,0)(20,30){2}\Dashline(0,0)(10,30){2} +%{\color{blue}% +%\Dashline*(40,0)(108:30){2} +%\Dashline*(40,0)(126:30){2} +%\Dashline*(40,0)(144:30){2} +%\Dashline*(40,0)(162:30){2}} +%\end{picture} +%\end{verbatim} +%\end{minipage} +%\hfill +%\begin{minipage}{0.4\textwidth}\raggedleft +%\begin{picture}(40,30) +%\put(0,0){\GraphGrid(40,30)} +%\Dashline(0,0)(40,10){2} +%\Dashline(0,0)(40,20){2} +%\Dashline(0,0)(40,30){2} +%\Dashline(0,0)(30,30){2} +%\Dashline(0,0)(20,30){2} +%\Dashline(0,0)(10,30){2} +%{\color{blue}% +%\Dashline*(40,0)(108:30){2} +%\Dashline*(40,0)(126:30){2} +%\Dashline*(40,0)(144:30){2} +%\Dashline*(40,0)(162:30){2}}% +%\end{picture} +%\end{minipage} +%\caption{Different length dashed lines with the same nominal dash length} +%\label{fig:dashedlines} +%\end{figure} +% +%^^A +%\item Analogous to |\Dashline|, a new command |\Dotline| draws a dotted +% line with the syntax: +% \begin{flushleft} +% |\Dotline|\parg{first point}\parg{end point}\marg{dot gap} +% \end{flushleft} +% See figures~\ref{fig:dashline} and~\ref{fig:dottedlines} for examples. +% +%\begin{figure}[htb]\unitlength=0.007\textwidth +%\begin{minipage}{0.55\textwidth} +%\begin{verbatim} +%\begin{picture}(40,30) +%\put(0,0){\GraphGrid(40,30)} +%\Dotline(0,0)(40,10){1.5}\Dotline(0,0)(40,20){1.5} +%\Dotline(0,0)(40,30){1.5}\Dotline(0,0)(30,30){1.5} +%\Dotline(0,0)(20,30){1.5}\Dotline(0,0)(10,30){1.5} +%{\color{red}\Dotline*(40,0)(108:30){1.5} +%\Dotline*(40,0)(126:30){1.5} +%\Dotline*(40,0)(144:30){1.5} +%\Dotline*(40,0)(162:30){1.5}}% +%\end{picture} +%\end{verbatim} +%\end{minipage} +%\hfill +%\begin{minipage}{0.4\textwidth}\raggedleft +%\begin{picture}(40,30) +%\put(0,0){\GraphGrid(40,30)} +%\Dotline(0,0)(40,10){1.5} +%\Dotline(0,0)(40,20){1.5} +%\Dotline(0,0)(40,30){1.5} +%\Dotline(0,0)(30,30){1.5} +%\Dotline(0,0)(20,30){1.5} +%\Dotline(0,0)(10,30){1.5} +%{\color{red}% +%\Dotline*(40,0)(108:30){1.5} +%\Dotline*(40,0)(126:30){1.5} +%\Dotline*(40,0)(144:30){1.5} +%\Dotline*(40,0)(162:30){1.5}}% +%\end{picture} +%\end{minipage} +%\caption{Different length dotted lines with the same nominal dot gap} +%\label{fig:dottedlines} +%\end{figure} +%^^A +% \item |\GraphGrid| is a command that draws a red grid under the drawing +% with lines separated |10\unitlength|s apart; it is described only with a +% comma separated couple of numbers, representing the base and the height +% of the grid, see figure~\ref{fig:dashline}; it's better to specify +% multiples of ten and the grid can be placed anywhere in the drawing +% canvas by means of |\put|, whose cartesian coordinates are multiples of +% 10; nevertheless the grid line distance is rounded to the nearest +% multiple of 10, while the point coordinates specified to |\put| are not +% rounded at all; therefore some care should be used to place the working +% grid on the drawing canvas. This grid is intended as an aid while +% drawing; even if you sketch your drawing on millimetre paper, the +% drawing grid turns out to be very useful; one must only delete or comment +% out the command when the drawing is finished. Several examples of usage of such grid are shown in several figures. +%^^A +% \item New trigonometric function macros have been computed by means of +% the functionalities of the |xfp| package. The compared to the other +% existing macros is that angles are specified in sexagesimal degrees, so +% that the user needs not transform to radians. The computations are done +% taking into account that abnormal values can occasionally be avoided, +% for example $\tan90^\circ$ must be avoided and replaced with a suitably +% large number, because the TeX\ system does not handle “infinity”. +% +% These trigonometric functions are used within the complex number macros; +% but if the user wants to use them the syntax is the following: +%\begin{flushleft} +% \cs{SinOf}\meta{angle}\texttt{to}\meta{control sequence} +%\\ +% \cs{CosOf}\meta{angle}\texttt{to}\meta{control sequence} +%\\ +% \cs{TanOf}\meta{angle}\texttt{to}\meta{control sequence} +%\end{flushleft} +% The \meta{control sequence} may then be used as a multiplying factor of a +% length. +% +%^^A +% \item Arcs can be drawn as simple circular arcs, or with one or two +% arrows at their ends (curved vectors); the syntax is: +%\begin{flushleft} +% \cs{Arc}\parg{center}\parg{starting point}\marg{angle}\\ +% \cs{VectorArc}\parg{center}\parg{starting point}\marg{angle}\\ +% \cs{VectorARC}\parg{center}\parg{starting point}\marg{angle}\\ +%\end{flushleft} +% If the angle is specified numerically it must be enclosed in braces, +% while if it is specified with a control sequence the braces (curly +% brackets) are not necessary. The above macro |\Arc| draws a simple +% circular arc without arrows; |\VectorArc| draws an arc with an arrow +% tip at the ending point; |\VectorARC| draws an arc with arrow tips at +% both ends; see figure~\ref{fig:arcs}. +% \begin{figure} +% \begin{minipage}{.48\textwidth} +% \begin{verbatim} +% \unitlength=0.5mm +% \begin{picture}(60,40) +% \put(0,0){\GraphGrid(60,40)} +% \Arc(0,20)(30,0){60} +% \VECTOR(0,20)(30,0)\VECTOR(0,20)(32.5,36) +% \VectorArc(0,20)(15,10){60} +% \put(20,20){\makebox(0,0)[l]{$60^\circ$}} +% \VectorARC(60,20)(60,0){-180} +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\textwidth}\centering +% \unitlength=0.5mm +% \begin{picture}(60,40) +% \put(0,0){\GraphGrid(60,40)} +% \Arc(0,20)(30,0){60} +% \VECTOR(0,20)(30,0)\VECTOR(0,20)(32.5,36) +% \VectorArc(0,20)(15,10){60} +% \put(20,20){\makebox(0,0)[l]{$60^\circ$}} +% \VectorARC(60,20)(60,0){-180} +% \end{picture} +% \end{minipage} +% \caption{Arcs and curved vectors}\label{fig:arcs} +% \end{figure} +%^^A +% \item A multitude of commands have been defined in order to manage +% complex numbers; actually complex numbers are represented as a comma +% separated pair of fractional numbers (here we use only cartesian +% coordinates). They are used to address specific points in the drawing +% plane, but also as operators so as to scale and rotate other objects. In +% the following \meta{vector} means a comma separated pair of fractional +% numbers, \meta{vector macro} means a macro that contains a comma +% separated pair of fractional numbers; \meta{angle macro} means a macro +% that contains the angle of a vector in sexagesimal degrees; +% \meta{argument} means a brace delimited numeric value, even a macro; +% \textit{macro} is a valid macro name, i.e.~a backslash followed by +% letters, or anything else that can receive a definition. A +% \emph{direction} of a vector is its versor;% the angle of a vector is +% the angle between the vector and the positive $x$ axis in +% counterclockwise direction, as generally directly used in the +% Euler formula $ \vec{v} = Me^{\mathrm{j}\varphi}$. +% +% {\footnotesize\begin{itemize} +% \item |\MakeVectorFrom|\meta{two arguments}|to|\meta{vector macro} +% \item |\CopyVect|\meta{first vector}|to|\meta{second vector macro} +% \item |\ModOfVect|\meta{vector}|to|\meta{macro} +% \item |\DirOfvect|\meta{vector}|to|\meta{versor macro} +% \item |\ModAndDirOfVect|\meta{vector}|to|\meta{1st macro}|and|\meta{2nd macro} +% \item |\DistanceAndDirOfVect|\meta{1st vector}|minus|\meta{2nd vector}|to|\meta{1st macro}|and|\meta{2nd macro} +% \item |\XpartOfVect|\meta{vector}|to|\meta{macro} +% \item |\YpartOfVect|\meta{vector}|to|\meta{macro} +% \item |\DirFromAngle|\meta{angle}|to|\meta{versor macro} +% \item |\ArgOfVect|\meta{vector}|to|\meta{angle macro} +% \item |\ScaleVect|\meta{vector}|by|\meta{scaling factor}|to|\meta{vector macro} +% \item |\ConjVect|\meta{vector}|to|\meta{conjugate vector macro} +% \item |\SubVect|\meta{first vector}|from|\meta{second vector}|to|\meta{vector macro} +% \item |\AddVect|\meta{first vector}|and|\meta{second vector}|to|\meta{vector macro} +% \item |\MultVect|\meta{first vector}|by|\meta{second vector}|to|\meta{vector macro} +% \item |\MultVect|\meta{first vector}|by*|\meta{second vector}|to|\meta{vector macro} +% \item |\DivVect|\meta{first vector}|by|\meta{second vector}|to|\meta{vector macro} +% \end{itemize}} +%^^A +% \item General curves can be drawn with the |pict2e| macro |\curve| but it +% requires the specification of the third-order Bézier-spline control +% points; sometimes it's better to be very specific with the control points +% and there is no other means to do a decent graph; sometimes the curves to +% be drawn are not so tricky and a general set of macros can be defined so +% as to compute the control points, while letting the user specify only the +% nodes through which the curve must pass, and the tangent direction of the +% curve in such nodes. Such commands are the following: +%\begin{itemize} +% +%\item \cs{Curve} to draw a sequence of arcs as explained above, using +% third order (cubic) Bézier splines. The starred version of this command +% fills the internal part of the curve with the current color; if the last +% arc finishes where the fist arc starts, it is clear what is the interior; +% if it does not, the driver (not the code of this package, but the +% driver between this code and the physical representation on paper or +% screen) assumes a straight line closure of the whole path. +% +%\item \cs{Qurve} similar to |\Curve|, but with second order (quadratic) +% Bézier splines. The starred version fills the interior with the current +% color +% +%\item \cs{CurveBetween} draws a single cubic Bézier spline between two +% given nodes and with two given directions vectors. +% +%\item \cs{CBezierBetween} draws a single cubic Bézier spline between two +% given nodes, with two given directions versors along which the +% control node distances are specified. This is the most general macro +% (rather difficult to use) with which not only the arc end points are +% specified but also the control nodes coordinates are given. +% +%\end{itemize} +% +% The main macro is |\Curve| and must be followed by an +% ``unlimited'' sequence of node-direction coordinates as a quadruple +% defined as +%\[ +% \parg{node coordinates}\aarg{direction vector} +%\] +% Possibly if a sudden change of direction has to be performed (cusp) +% another item can be inserted after one of those quadruples in the form +%\[ +% \mbox{\dots\parg{...}\aarg{...}\oarg{new direction vector}\parg{...}\aarg{...}\dots} +%\] +% +% Possibly it is necessary to specifiy the “tension” or the “looseness” +% of a specific Bézier arc; such tension parameters range from 0 (zero) +% to~4; the zero value implies a very stiff arc, as if it was a string +% subject to a high tension (i.e. with zero looseness); a value of~4 +% implies a very low tension (very high looseness), almost as if the string +% was not subject to any tension. In \MF\ or \MP\ language such a concept +% is used very often; in this package, where the Hobby algorithms are +% not used, the parameter value appears to mean the opposite of tension. +% A couple of comma separated tension values may be optionally used, they +% are separated with a semicolon form the direction vector, +% and they apply to the arc terminating with the last node; their +% specification must +% precede any possible change of tangent according to this +% syntax\footnote{The tension may be specified only for cubic splines, +% because the quadratic ones do not use enough parameters to control the +% tension; not all commands for drawing cubic splines accept this +% optional tension specification.}: +%\[ +%\mbox{\dots\parg{...}\aarg{\upshape{\em direction vector}\texttt{;}{\em start tension}|,|{\em end tension}}\parg{...}\aarg{...}\dots} +%\] +% +% The |\Curve| macro does not (still) have facilities for cycling the path, +% that is to close the path from the last specified node-direction to the +% first specified node-direction; but, as already mentioned, if the ending +% node of the last arc does not coincide with the stating node of the +% first arc, a straight line is assumed to join such nodes; this line does +% not get drawn, but with starred commands no lines are drawn because only +% the interior is coloured. +% The tangent direction need not be specified with a unit vector, although +% only its direction is relevant; the scaling of the specified direction +% vector to a unit vector is performed by the macro itself. +% Therefore one cannot specify the fine tuning of the curve convexity as it +% can be done with other programs or commands, as for example with \MF\ +% or the |pgf/tikz| package and environment. See figure~\ref{fig:curve} for +% an example. +% \begin{figure}[htb] +% \begin{minipage}{.48\textwidth} +% \begin{verbatim} +% \unitlength=8mm\relax +% \begin{picture}(5,5) +% \put(0,0){\framebox(5,5){}}\thicklines\roundcap +% \Curve(2.5,0)<1,1>(5,3.5)<0,1>% +% (4,5)<-1,0>(2.5,3.5)<-.5,-1.2>[-.5,1.2]% +% (1,5)<-1,0>(0,3.5)<0,-1>(2.5,0)<1,-1> +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\textwidth}\raggedleft\relax +% \unitlength=8mm\relax +% \begin{picture}(5,5) +% \put(0,0.5){\put(0,0){\framebox(5,5){}}\thicklines\roundcap +% \Curve(2.5,0)<1,1>(5,3.5)<0,1>(4,5)<-1,0>(2.5,3.5)<-0.5,-1.2>[-0.5,1.2](1,5)<-1,0>(0,3.5)<0,-1>(2.5,0)<1,-1>} +% \end{picture} +% \end{minipage} +% \caption{A heart shaped curve with cusps drawn with \texttt{\string\Curve}} +% \label{fig:curve} + +%\vspace*{2\baselineskip} +% +% \begin{minipage}{.48\textwidth} +% \begin{verbatim} +% \unitlength=8mm\relax +% \begin{picture}(5,5) +% \put(0,0){\framebox(5,5){}}\thicklines\roundcap +% \color{green}\relax +% \Curve*(2.5,0)<1,1>(5,3.5)<0,1>% +% (4,5)<-1,0>(2.5,3.5)<-.5,-1.2>[-.5,1.2]% +% (1,5)<-1,0>(0,3.5)<0,-1>(2.5,0)<1,-1> +% \end{picture} +% \end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{.48\textwidth}\raggedleft\relax +% \unitlength=8mm\relax +% \begin{picture}(5,5) +% \put(0,0.5){\put(0,0){\framebox(5,5){}}\thicklines\roundcap +% \color{green}\relax +% \Curve*(2.5,0)<1,1>(5,3.5)<0,1>(4,5)<-1,0>(2.5,3.5)<-0.5,-1.2>[-0.5,1.2](1,5)<-1,0>(0,3.5)<0,-1>(2.5,0)<1,-1>} +% \end{picture} +% \end{minipage} +%\caption{Coloring the inside of a closed path drawn with \texttt{\string\Curve*}} +%\label{fig:colored-curve} + +% \end{figure} +% +% With the starred version of |\Curve|, instead of stroking the contour, +% the macro fills up the contour with the selected current color, +% figure~\ref{fig:colored-curve}. +% +% Figure~\ref{fig:arcspline} shows a geometric construction that contains the geometric elements and symbols used to determine the parameters of a cubic spline required to draw a quarter circle. This construction containa many of the commands described so far. +% +%\begin{figure}[p] +%\begin{minipage}{\linewidth}\small +%\begin{verbatim} +%\unitlength=0.007\textwidth +%\begin{picture}(100,90)(-50,-50) +%\put(-50,0){\vector(1,0){100}}\put(50,1){\makebox(0,0)[br]{$x$}}% +%\put(20,-1){\makebox(0,0)[t]{$s$}}% +%\put(0,0){\circle*{2}}\put(-1,-1){\makebox(0,0)[tr]{$M$}}% +%\legenda(12,-45){s=\overline{MP_2}=R\sin\theta}% +%\put(0,-50){\vector(0,1){90}}% +%\put(1,40){\makebox(0,0)[tl]{$y$}}% +%\put(0,-40){\circle*{2}}\put(1,-41){\makebox(0,0)[lt]{$C$}}% +%\segment(0,-40)(-40,0)\segment(0,-40)(40,0)% +%\put(-41,1){\makebox(0,0)[br]{$P_1$}}\put(-40,0){\circle*{2}}% +%\put(41,1){\makebox(0,0)[bl]{$P_2$}}\put(40,0){\circle*{2}}% +%\put(0,0){\linethickness{1pt}\Arc(0,-40)(40,0){90}}% +%\segment(-40,0)(-20,20)\put(-20,20){\circle*{2}}% +%\put(-20,21.5){\makebox(0,0)[b]{$C_1$}}% +%\segment(40,0)(20,20)\put(20,20){\circle*{2}}% +%\put(20,21.5){\makebox(0,0)[b]{$C_2$}}% +%\put(0,-40){\put(0,56.5685){\circle*{2}}% +%\put(1,58){\makebox(0,0)[bl]{$P$}}}% +%\VectorARC(0,-40)(15,-25){45}\put(10,-18){\makebox(0,0)[c]{$\theta$}}% +%\VectorARC(40,0)(20,0){-45}\put(19,5){\makebox(0,0)[r]{$\theta$}}% +%\VectorARC(-40,0)(-20,0){45}\put(-19,5){\makebox(0,0)[l]{$\theta$}}% +%\put(-20,-18){\makebox(0,0)[bl]{$R$}}% +%\put(-32,13){\makebox(0,0)[bl]{$K$}}% +%\put(32,13){\makebox(0,0)[br]{$K$}}% +%\end{picture} +%\end{verbatim} +%\end{minipage}\vspace{\stretch{1}} +% +%\begin{minipage}{\linewidth}\centering +%\unitlength=0.007\textwidth +%\begin{picture}(100,90)(-50,-50) +%\put(-50,0){\vector(1,0){100}}\put(50,1){\makebox(0,0)[br]{$x$}}% +%\put(20,-1){\makebox(0,0)[t]{$s$}}% +%\put(0,0){\circle*{2}}\put(-1,-1){\makebox(0,0)[tr]{$M$}}% +%\legenda(12,-45){s=\overline{MP_2}=R\sin\theta}% +%\put(0,-50){\vector(0,1){90}}% +%\put(1,40){\makebox(0,0)[tl]{$y$}}% +%\put(0,-40){\circle*{2}}\put(1,-41){\makebox(0,0)[lt]{$C$}}% +%\segment(0,-40)(-40,0)\segment(0,-40)(40,0)% +%\put(-41,1){\makebox(0,0)[br]{$P_1$}}\put(-40,0){\circle*{2}}% +%\put(41,1){\makebox(0,0)[bl]{$P_2$}}\put(40,0){\circle*{2}}% +%\put(0,0){\linethickness{1pt}\Arc(0,-40)(40,0){90}}% +%\segment(-40,0)(-20,20)\put(-20,20){\circle*{2}}% +%\put(-20,21.5){\makebox(0,0)[b]{$C_1$}}% +%\segment(40,0)(20,20)\put(20,20){\circle*{2}}% +%\put(20,21.5){\makebox(0,0)[b]{$C_2$}}% +%\put(0,-40){\put(0,56.5685){\circle*{2}}% +%\put(1,58){\makebox(0,0)[bl]{$P$}}}% +%\VectorARC(0,-40)(15,-25){45}\put(10,-18){\makebox(0,0)[c]{$\theta$}}% +%\VectorARC(40,0)(20,0){-45}\put(19,5){\makebox(0,0)[r]{$\theta$}}% +%\VectorARC(-40,0)(-20,0){45}\put(-19,5){\makebox(0,0)[l]{$\theta$}}% +%\put(-20,-18){\makebox(0,0)[bl]{$R$}}% +%\put(-32,13){\makebox(0,0)[bl]{$K$}}% +%\put(32,13){\makebox(0,0)[br]{$K$}}% +%\end{picture} +%\end{minipage} +%\caption{The code to display the Nodes and control points for an arc to +% be approximated with a cubic Bézier spline} +%\label{fig:arcspline} +%\end{figure} +% +% +% To show what you can do with |\CurveBetween| see the code and result +% shown in figure~\ref{fig:curva-due-punti}. Notice the effect of changing the directions at both or a the end nodes os a single cubic spline. The directions are conveniently expressed with unit vectors described by polar coordinates. + +%\begin{figure}\centering\unitlength=0.004\textwidth +%\begin{picture}(220,120)(-50,-20) +%\put(0,60){\Line(-50,0)(50,0) +%\CurveBetween-50,0and50,0WithDirs15:1and{-15:1} +%\CurveBetween-50,0and50,0WithDirs30:1and{-30:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{-45:1} +%\CurveBetween-50,0and50,0WithDirs60:1and{-60:1} +%\CurveBetween-50,0and50,0WithDirs75:1and{-75:1} +%\CurveBetween-50,0and50,0WithDirs90:1and{-90:1}} +%\put(120,60){% +%\Line(-50,0)(50,0) +%\CurveBetween-50,0and50,0WithDirs15:1and{15:1} +%\CurveBetween-50,0and50,0WithDirs30:1and{30:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{45:1} +%\CurveBetween-50,0and50,0WithDirs60:1and{60:1} +%\CurveBetween-50,0and50,0WithDirs75:1and{75:1} +%\CurveBetween-50,0and50,0WithDirs90:1and{90:1}} +%\put(0,0){% +%\Line(-50,0)(50,0) +%\CurveBetween-50,0and50,0WithDirs45:1and{-15:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{-30:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{-45:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{-60:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{-75:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{-90:1}} +%\put(120,0){% +%\Line(-50,0)(50,0) +%\CurveBetween-50,0and50,0WithDirs45:1and{15:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{30:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{45:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{60:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{75:1} +%\CurveBetween-50,0and50,0WithDirs45:1and{90:1}} +%\end{picture} +%\caption{Curves between two points with different start and end slopes}\label{fig:curva-due-punti} +%\end{figure} +% +% A little more complicated is the use of the |\CBezierBetween| macro, +% figure~\ref{fig:Cbezier}. The directions are specified with unit +% vectors in polar form; the control points are specified by adding their +% distances from their neighbouring nodes; actually the right distance +% is maintained to the value~1, while the left one increases from~4 to~10. +% The black line corresponds to the standard |\CurveBetween| where the +% default distance is computed by default to trace an arc of a circle and +% is approximately~3.5. +% +%\begin{figure}[!tb] +%\begin{minipage}[t]{0.52\textwidth} +%\begin{verbatim} +%\unitlength=0.1\textwidth +%\begin{picture}(10,3) +%\CurveBetween0,0and10,0WithDirs1,1and{1,-1} +%\color{red}% +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists4And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists6And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists8And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists10And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists12And{1} +%\end{picture} +%\end{verbatim} +%\end{minipage} +%\hfill +%\begin{minipage}{0.40\textwidth}\raggedleft +%\unitlength=0.1\textwidth +%\begin{picture}(10,3)(0,1.25) +%\CurveBetween0,0and10,0WithDirs1,1and{1,-1} +%\color{red}% +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists4And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists6And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists8And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists10And{1} +%\CbezierBetween0,0And10,0 WithDirs45:1And-45:1UsingDists12And{1} +%\end{picture} +%\end{minipage} +%\caption{Comparison between similar arcs drawn with \cs{CurveBetween} (black) +% and \cs{CbezierTo} (red)} +%\label{fig:Cbezier} +%\end{figure} +% +% In figure~\ref{fig:tensions} the effect of tension specification is +% shown. The red line corresponds to the default tension, since the +% tension values are not specified. The black lines correspond to the +% various values used in the various commands to the |\Curve| macro. +% With a tension of zero, the spline is almost coincident wit the +% horizontal base line of the frame. Increasing the tension value +% to~4.5, the curved becomes taller and taller, until it wraps itself +% displaying an evident loop. We would say that the value of ~2 is a +% reasonable maximum and increasing that tension value is just to +% obtain special effects. +% +%\begin{figure}[!htb]\centering +%\begin{minipage}{0.48\textwidth}\small +%\begin{verbatim} +%\raggedleft\unitlength=0.01\textwidth +%\begin{picture}(70,70) +%\put(0,0){\color{blue}\frame(70,70){}} +%\put(0,0){\color{red}\Curve(0,0)<1,1>(70,0)<1,-1>} +%\Curve(0,0)<1,1>(70,0)<1,-1;0,0> +%\Curve(0,0)<1,1>(70,0)<1,-1;0.2,0.2> +%\Curve(0,0)<1,1>(70,0)<1,-1;2,2> +%\Curve(0,0)<1,1>(70,0)<1,-1;4.5,4.5> +%\Curve(0,0)<1,1>(70,0)<1,-1;0,3> +%\Curve(0,0)<1,1>(70,0)<1,-1;3,0> +%\end{picture} +%\end{verbatim} +%\end{minipage} +%\hfill +%\begin{minipage}{0.46\textwidth} +%\raggedleft\unitlength=0.01\textwidth +%\begin{picture}(70,70) +%\put(0,0){\color{blue}\framebox(70,70){}} +%\put(0,0){\color{red}\Curve(0,0)<1,1>(70,0)<1,-1>} +%\Curve(0,0)<1,1>(70,0)<1,-1;0,0> +%\Curve(0,0)<1,1>(70,0)<1,-1;0.2,0.2> +%\Curve(0,0)<1,1>(70,0)<1,-1;2,2> +%\Curve(0,0)<1,1>(70,0)<1,-1;4.5,4.5> +%\Curve(0,0)<1,1>(70,0)<1,-1;0,3> +%\Curve(0,0)<1,1>(70,0)<1,-1;3,0> +%\end{picture} +%\end{minipage} +%\caption{The effects of tension factors}\label{fig:tensions} +%\end{figure} +% +% Figure~\ref{fig:sinewave} displays two approximations of a sine wave; +% Bézier splines can approximate transcendental curves, but the +% approximation may be a poor one, depending on the approximated curve, +% if few arcs are used to draw it. With arcs specified with more +% complicated macros the approximation is better even with a lower number +% of arcs. With many arcs it is possible to approximate almost anything. +% On the left side a modest approximation is obtained with just three +% standard arcs obtained with |\Curve| and four node specifications; +% on the right we have just two arcs created with |CBezierBetween| +% with tension specification and control point distances; this drawing +%is almost undistinguishable from a real sinusoid. +% +%\begin{figure}[!htb] +%\begin{minipage}{\linewidth} +%\begin{verbatim} +%\unitlength=0.01\textwidth +%\begin{picture}(100,50)(0,-25) +%\put(0,0){\VECTOR(0,0)(45,0)\VECTOR(0,-25)(0,25) +%\Zbox(45,0)[br]{x}\Zbox(0,26)[tl]{y} +%\Curve(0,0)<77:1>(10,20)<1,0;2,0.4>(30,-20)<1,0;0.4,0.4>(40,0)<77:1;0.4,2> +%} +%\put(55,0){\VECTOR(0,0)(45,0)\VECTOR(0,-25)(0,25) +%\Zbox(45,0)[br]{x}\Zbox(0,26)[tl]{y} +%\CbezierBetween0,0And20,0WithDirs77:1And-77:1UsingDists28And{28} +%\CbezierBetween20,0And40,0WithDirs-77:1And77:1UsingDists28And{28}} +%\end{picture} +%\end{verbatim} +%\end{minipage}\vspace{\baselineskip} +% +%\begin{minipage}{\linewidth} +%\unitlength=0.01\textwidth +%\begin{picture}(100,50)(0,-25) +%\put(0,0){\VECTOR(0,0)(45,0)\VECTOR(0,-25)(0,25) +%\Zbox(45,0)[br]{x}\Zbox(0,26)[tl]{y} +%\Curve(0,0)<77:1>(10,20)<1,0;2,0.4>(30,-20)<1,0;0.4,0.4>(40,0)<77:1;0.4,2> +%} +%\put(55,0){\VECTOR(0,0)(45,0)\VECTOR(0,-25)(0,25) +%\Zbox(45,0)[br]{x}\Zbox(0,26)[tl]{y} +%\CbezierBetween0,0And20,0WithDirs77:1And-77:1UsingDists28And{28} +%\CbezierBetween20,0And40,0WithDirs-77:1And77:1UsingDists28And{28}} +%\end{picture} +%\end{minipage} +%\caption{A sequence of arcs; the left figure has been drawn with the +% \cs{Curve} command with a sequence of four couples of point-direction +% arguments; the right figure has been drawn with two commands +% \cs{CbezierBetween} that include also the specification of the control +% points} +%\label{fig:sinewave} +%\end{figure} +% +% In figure~\ref{fig:quadratic-arcs} some lines drawn with quadratic +% splines by means of the |\Qurve| macro are shown. In the left there are +% some open and closed curves inscribed within a square. On the right a +% “real" circle is compared to a quadratic spline circle; the word “real” +% is emphasised because it actually is an approximation with four +% quarter-circle cubic splines that, in spite of being drawn with third +% degree parametric polynomials, approximate very well a real circle; on +% the opposite the quadratic spline circle is clearly a poor approximation +% even if the maximum radial error amounts just to about 6\% of the radius. +% +%\begin{figure}[p] +%\begin{minipage}{\linewidth} +%\begin{Verbatim}[fontsize=\setfontsize{7.75}] +%\unitlength=0.0045\textwidth +%\begin{picture}(100,100) +%\put(0,0){\framebox(100,100){}} +%\put(50,50){% +% \Qurve(0,-50)<1,0>(50,0)<0,1>(0,50)<-1,0>(-50,0)<0,-1>(0,-50)<1,0> +%\color{green} +% \Qurve*(0,-50)<0,1>(50,0)<1,0>[-1,0](0,50)<0,1>[0,-1](-50,0)<-1,0>[1,0](0,-50)<0,-1> +%} +%\Qurve(0,0)<1,4>(50,50)<1,0>(100,100)<1,4> +%\put(5,50){\Qurve(0,0)<1,1.5>(22.5,20)<1,0>(45,0)<1,-1.5>% +%(67.5,-20)<1,0>(90,0)<1,1.5>} +%\Zbox(0,0)[tc]{0,0}\Zbox(100,0)[tc]{100,0} +%\Zbox(100,100)[bc]{100,100}\Zbox(0,100)[bc]{0,100} +%\Pall[2](0,0)\Pall[2](100,0)\Pall[2](100,100)\Pall[2](0,100) +%\end{picture} +%\hfill +%\begin{picture}(100,100) +%\put(0,0){\framebox(100,100){}} +%\put(50,50){% +%\Qurve(0,-50)<1,0>(50,0)<0,1>(0,50)<-1,0>(-50,0)<0,-1>(0,-50)<1,0> +%\Curve(0,-50)<1,0>(50,0)<0,1>(0,50)<-1,0>(-50,0)<0,-1>(0,-50)<1,0>} +%\Zbox(50,50)[t]{O}\Pall[2](50,50)\put(50,50){\Vector(45:50)}\Zbox(67,70)[tl]{R} +%\end{picture} +%\end{Verbatim} +%\end{minipage}\vspace{2\baselineskip} +% +%\begin{minipage}{\linewidth} +%\unitlength=0.0045\textwidth +%\begin{picture}(100,100) +%\put(0,0){\framebox(100,100){}} +%\put(50,50){\Qurve(0,-50)<1,0>(50,0)<0,1>(0,50)<-1,0>(-50,0)<0,-1>(0,-50)<1,0>} +%\put(50,50){\color{green}% +%\Qurve*(0,-50)<0,1>(50,0)<1,0>[-1,0](0,50)<0,1>[0,-1](-50,0)<-1,0>[1,0](0,-50)<0,-1>} +%\Qurve(0,0)<1,4>(50,50)<1,0>(100,100)<1,4> +%\put(5,50){\Qurve(0,0)<1,1.5>(22.5,20)<1,0>(45,0)<1,-1.5>(67.5,-20)<1,0>(90,0)<1,1.5>} +%\Zbox(0,0)[tc]{0,0}\Zbox(100,0)[tc]{100,0} +%\Zbox(100,100)[bc]{100,100}\Zbox(0,100)[bc]{0,100} +%\Pall[2](0,0)\Pall[2](100,0)\Pall[2](100,100)\Pall[2](0,100) +%\end{picture} +%\hfill +%\begin{picture}(100,100) +%\put(0,0){\framebox(100,100){}} +%\put(50,50){\Qurve(0,-50)<1,0>(50,0)<0,1>(0,50)<-1,0>(-50,0)<0,-1>(0,-50)<1,0> +%\Curve(0,-50)<1,0>(50,0)<0,1>(0,50)<-1,0>(-50,0)<0,-1>(0,-50)<1,0>} +%\Zbox(50,50)[t]{O}\Pall[2](50,50)\put(50,50){\Vector(45:50)}\Zbox(67,70)[tl]{R} +%\end{picture} +%\end{minipage} +% +%\caption{\rule{0pt}{4ex}Several graphs drawn with quadratic Bézier splines. On the right a quadratic spline circle is compared with a cubic line circle.} +%\label{fig:quadratic-arcs} +%\end{figure} +% +% Notice that the previous version of |curve2e| contained an error and +% would color the outside of the green four-pointed star. +% The |curve2e-v161|, attached to this bundle, has been corrected; +% therefore it is not actually identical to the previous version, +% although the latter one performed correctly for everything else except +% for color-filled quadratic paths. +% +% \end{enumerate} +% +% +% In spite of the relative simplicity of the macros contained in this +% package, the described macros, as well as the original ones included in +% the |pict2e| package, allow to produce fine drawings that were +% unconceivable with the original \LaTeX\ picture environment. Leslie +% Lamport himself announced an extension to his environment when \LaTeXe\ +% was first released in 1994; in the |latexnews| news-letter of December +% 2003; the first implementation was announced; the first version of this +% package was issued in 2006. It was time to have a better drawing +% environment; this package is a simple attempt to follow the initial path +% while extending the drawing facilities; but Till Tantau's |pgf| +% package has gone much farther. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Remark} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% There are other packages in the \textsc{ctan} archives that deal with +% tracing curves of various kinds. |PSTricks| and |tikz/pgf| are the most +% powerful ones. +% But there is also the package |curves| that is intended to draw almost +% anything by using little dots or other symbols partially superimposed to +% one another. It uses only quadratic Bézier curves and the curve tracing +% is eased by specifying only the curve nodes, without specifying the +% control nodes; with a suitable option to the package call it is possible +% to reduce the memory usage by using short straight segments drawn with +% the PostScript facilities offered by the |dvips| driver. +% +% Another package |ebezier| performs about the same as |curve2e| but draws +% its Bézier curves by using little dots partially superimposed to one +% another. The documentation is quite interesting but since it explains +% very clearly what exactly are the Bézier splines. Apparently |ebezier| +% should be used only for dvi output without recourse to PostScript machinery. +% +% The |picture| package extends the performance of the |picture| +% environment (extended with \texttt{pict2e}) by accepting coordinates +% and lengths in real absolute dimensions, not only as multiples of +% |\unitlength|; it provides commands to extend that functionality to +% other packages. In certain circumstances it is very useful. +% +% Package \texttt{xpicture} builds over the |picture| \LaTeX\ environment +% so as to allow to draw the usual curves that are part of an introductory +% analytic geometry course; lines, circles, parabolas, ellipses, +% hyperbolas, and polynomials; the syntax is very comfortable; for all +% these curves it uses the quadratic Bézier splines. +% +% Package |hobby| extends the cubic Bézier spline handling with the +% algorithms John Hobby created for \MF\ and \MP. But by now this package +% interfaces very well with |tikz|; it has not (yet) been adapted to the +% common |picture| environment, even extended with |pict2e|, and, why not, +% with |curve2e|. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Acknowledgements} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% I wish to express my deepest thanks to Michel Goosens who spotted some +% errors and very kindly submitted them to me so that I was able to correct +% them. +% +% Josef Tkadlec and the author collaborated extensively in order to make a +% better real long division so as to get correctly the quotient fractional +% part and to avoid as much as possible any numeric overflow; many Josef's +% ideas are incorporated in the macro that was implemented in the previous +% version of this package, although the macro used by Josef was slightly +% different. Both versions aim/aimed at a better accuracy and at widening +% the operand ranges. In this version we abandoned the long division macro, +% and substituted it with the floating point division provided by the +% |xfp| package. +% +% Daniele Degiorgi spotted a fault in the kernel definition of +% |\linethickness| that heavily influenced also |curve2e|; see below in +% the code documentation part. +% +% Thanks also to Jin-Hwan Cho and Juho Lee who suggested a small but +% crucial modification in order to have \texttt{curve2e} work smoothly also +% with XeTeX (XeLaTeX). Actually if version 0.2x or later, dated 2009/08/05 +% or later, of |pict2e| is being used, such modification is not necessary, +% but it's true that it becomes imperative if older versions are used. +% +% \StopEventually{% +% \begin{thebibliography}{9} +% \bibitem{pict2e} Gäßlein H., Niepraschk R., and Tkadlec J. +% \emph{The \texttt{pict2e} package}, 2014, PDF documentation of +% \texttt{pict2e}; this package is part of any modern complete distribution +% of the \TeX\ system. In case of a basic or partial system installation, +% the package may be installed by means of the specific facilities of the +% distribution. It may be read by means of the line command \texttt{texdoc +% pict2e}. +% \end{thebibliography} +% } +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Source code} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Some preliminary extensions to the \texttt{pict2e} package} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The necessary preliminary code has already been introduced. Here we +% require the \texttt{color} package and the \texttt{pict2e} one; for the +% latter one we make sure that a sufficiently recent version is used. +% If you want to use package \texttt{xcolor}, load it after +% \texttt{curve2e}. +% +% Here we load also the |xparse| and |xfp| packages because we use their +% functionalities; but we do load them only if they are not already loaded +% with or without options; nevertheless we warn the user who wants to load +% them explicitly, to do this action before loading \texttt{curve2e}. +% The |xfp| package is absolutely required; if this package can not found +% it in the \TeX\ system installation, the loading of this package is +% aborted, and the previous version 1.61 of |curve2e| is loaded in its +% place; the overall functionalities should non change much, nevertheless +% the functionalities of |xfp| are not available. +%\iffalse +%<*package> +%\fi +% \begin{macrocode} +\IfFileExists{xfp.sty}{% + \RequirePackage{color} + \RequirePackageWithOptions{pict2e}[2014/01/01] + \@ifl@aded{sty}{xparse}{}{\RequirePackage{xparse}} + \@ifl@aded{sty}{xfp}{}{\RequirePackage{xfp}}% +}{% + \RequirePackage{curve2e-v161}% + \PackageWarningNoLine{curve2e}{% + Package xfp is required, but apparently\MessageBreak% + such package cannot be found in this \MessageBreak% + TeX system installation\MessageBreak% + Either your installation is not complete \MessageBreak% + or it is older than 2018-10-17.\MessageBreak% + \MessageBreak% + ***************************************\MessageBreak% + Version 1.61 of curve2e has been loaded\MessageBreak% + instead of the current version\MessageBreak% + ***************************************\MessageBreak}% + \endinput +} +% \end{macrocode} +% +% The next macros are just for debugging. With the \texttt{trace} package +% it would probably be better to define other macros, but this is not for +% the users, but for the developers. +% \begin{macrocode} +\def\TRON{\tracingcommands\tw@ \tracingmacros\tw@}% +\def\TROF{\tracingcommands\z@ \tracingmacros\z@}% +% \end{macrocode} +% +% Next we define some new dimension registers that will be used by the +% subsequent macros; should they be already defined, there will not be any +% redefinition; nevertheless the macros should be sufficiently protected +% so as to avoid overwriting register values loaded by other macro +% packages. +% \begin{macrocode} +\ifx\undefined\@tdA \newdimen\@tdA \fi +\ifx\undefined\@tdB \newdimen\@tdB \fi +\ifx\undefined\@tdC \newdimen\@tdC \fi +\ifx\undefined\@tdD \newdimen\@tdD \fi +\ifx\undefined\@tdE \newdimen\@tdE \fi +\ifx\undefined\@tdF \newdimen\@tdF \fi +\ifx\undefined\defaultlinewidth \newdimen\defaultlinewidth \fi +% \end{macrocode} +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Line thickness macros} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% It is better to define a macro for setting a different value for the line +% and curve thicknesses; the `|\defaultlinewidth| should contain the +% equivalent of |\@wholewidth|, that is the thickness of thick lines; thin +% lines are half as thick; so when the default line thickness is specified +% to, say, 1pt, thick lines will be 1pt thick and thin lines will be 0.5pt +% thick. The default whole width of thick lines is 0,8pt, but this is +% specified in the kernel of \LaTeX\ and\slash or in \texttt{pict2e}. On +% the opposite it is necessary to redefine |\linethickness| because the +% \LaTeX\ kernel global definition does not hide the space after the closed +% brace when you enter something such as |\linethickness{1mm}| followed by +% a space or a new line.\footnote{Thanks to Daniele Degiorgi +% (\texttt{degiorgi@inf.ethz.ch}).} +% \begin{macrocode} +\gdef\linethickness#1{% +\@wholewidth#1\@halfwidth.5\@wholewidth\ignorespaces}% +\newcommand\defaultlinethickness[1]{\defaultlinewidth=#1\relax +\def\thicklines{\linethickness{\defaultlinewidth}}% +\def\thinlines{\linethickness{.5\defaultlinewidth}}\thinlines \ignorespaces}% +% \end{macrocode} +% The |\ignorespaces| at the end of these macros is for avoiding spurious +% spaces to get into the picture that is being drawn, because +% these spaces introduce picture deformities often difficult to spot and +% eliminate. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Improved line and vector macros} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The macro |\LIne| allows to draw a line with arbitrary inclination +% as if it was a polygonal with just two vertices; actually it joins the +% canvas coordinate origin with the specified relative coordinate; +% therefore this object must be set in place by means of a |\put| command. +% Since its starting point is always at a relative 0,0 coordinate point +% inside the box created with |\put|, the two arguments define the +% horizontal and the vertical component respectively. +% \begin{macrocode} +\def\LIne(#1){{\GetCoord(#1)\@tX\@tY + \moveto(0,0) + \pIIe@lineto{\@tX\unitlength}{\@tY\unitlength}\strokepath}\ignorespaces +}% +% \end{macrocode} +% +% A similar macro |\segment| operates between two explicit points with +% absolute coordinates, instead of relative to the position specified by a +% |\put| command; it resorts to the |\polyline| macro that shall be +% defined in a while. The |\@killglue| command might be unnecessary, but it +% does not harm; it eliminates any explicit or implicit spacing that might +% precede this command. +% \begin{macrocode} +\def\segment(#1)(#2){\@killglue\polyline(#1)(#2)}% +% \end{macrocode} +% By passing its ending points coordinates to the |\polyline| macro, both +% macro arguments are a pair of coordinates, not their components; in other +% words, if $P_1=(x_1, y_2)$ and $P_2=(x_2, y_2)$, then the first argument +% is the couple $x_1, y_1$ and likewise the second argument is $x_2, y_2$. +% Notice that since |\polyline| accepts also the corner coordinates in +% polar form, also|\segment| accepts the polar form. Please remember that +% the decimal separator is the decimal \emph{point}, while the \emph{comma} +% acts as coordinate separator. This recommendation is particularly +% important for non-English speaking users, since in all other languages +% the comma must be used as the decimal separator. +% +% The |\line| macro is redefined by making use of a division routine +% performed in floating point arithmetics; for this reason the \LaTeX\ +% kernel and the overall \TeX\ system installation must be as recent as +% the release date of the \texttt{xfp} package, i.e. 2018-10-17. +% The floating point division macro receives in input two fractional +% numbers and yields on output their fractional ratio. +% Notice that this command |\line| should follow the same syntax as the +% original pre~1994 \LaTeX\ version; but the new definition accepts the +% direction coefficients in polar mode; that is, instead of specifying a +% slope of $30^\circ$ with the actual sine and cosine (or values +% proportional to such functions), for example |(0.5,0.866025)|, you may +% specify it as |(30:1)|, i.e. as a unit vector with the required slope of +% $30^\circ$. +% +% The beginning of the macro definition is the same as that of \texttt{pict2e}: +% \begin{macrocode} +\def\line(#1)#2{\begingroup + \@linelen #2\unitlength + \ifdim\@linelen<\z@\@badlinearg\else +% \end{macrocode} +% but as soon as it is verified that the line length is not negative, +% things change remarkably; in facts the machinery for complex numbers is +% invoked. This makes the code much simpler, not necessarily more +% efficient; nevertheless |\DirOfVect| takes the only macro argument (that +% actually contains a comma separated pair of fractional numbers) and +% copies it to |\Dir@line| (an arbitrarily named control sequence) after +% re-normalizing to unit magnitude; this is passed to |GetCoord| that +% separates the two components into the control sequences |\d@mX| and +% |\d@mY|; these in turn are the values that are actually operated upon by +% the subsequent commands. +% \begin{macrocode} + \expandafter\DirOfVect#1to\Dir@line + \GetCoord(\Dir@line)\d@mX\d@mY +% \end{macrocode} +% The normalised vector direction is actually formed with the directing +% cosines of the line direction; since the line length is actually the +% horizontal component for non vertical lines, it is necessary to compute +% the actual line length for non vertical lines by dividing the given +% length by the magnitude of the horizontal cosine |\d@mX|, and the line +% length is accordingly scaled: +% \begin{macrocode} + \ifdim\d@mX\p@=\z@\else + \edef\sc@lelen{\fpeval{1 / abs(\d@mX)}}\relax + \@linelen=\sc@lelen\@linelen + \fi +% \end{macrocode} +% Of course, if the line is vertical this division must not take place. +% Finally the \texttt{moveto}, \texttt{lineto} and \texttt{stroke} language +% keywords are invoked by means of the internal \texttt{pict2e} commands in +% order to draw the line. Notice that even vertical lines are drawn with +% the PDF language commands instead of resorting to the DVI low level +% language that was used in both \texttt{pict2e} and the original +% (pre 1994) \texttt{picture} commands; it had a meaning in the old times, +% but it certainly does not have any, since lines are drawn by the driver +% that produces the output in a human visible document form, not by \TeX\ +% the program. +% \begin{macrocode} + \moveto(0,0) + \pIIe@lineto{\d@mX\@linelen}{\d@mY\@linelen}% + \strokepath + \fi +\endgroup\ignorespaces}% +% \end{macrocode} +% The new definition of the command |\line|, besides the ease with which is +% readable, does not do different things from the definition of |pict2e| +% 2009, but it did perform in a better way compared to the 2004 version +% that was limited to integer direction coefficients up to 999 in +% magnitude. In any case this |curve2e| version accepts polar coordinates +% as slope couples, making it much simpler to draw lines with specific +% slopes. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Dashed and dotted lines} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Dashed and dotted lines are very useful in technical drawings; here we +% introduce four macros that help drawing them in the proper way; besides +% the obvious difference between the use of dashes or dots, they may refer +% in a different way to the end points that must be specified to the +% various macros. +% +% The coordinates of the first point $P_1$, where le line starts, are +% always referred to the origin of the coordinate axes; the end point $P_2$ +% coordinates with the first macro type are referred to the origin of the +% axes, while with the second macro type they are referred to $P_1$; both +% macro types have their usefulness and figures~\ref{fig:dashedlines} +% and~\ref{fig:dottedlines} show how to use these macros. +% +% We distinguish these macros with an asterisk; the unstarred version is +% the first macro type, while the starred one refers to the second macro +% type. +% +% The above mentioned macros create dashed lines between two given +% points, with a dash length that must be specified, or dotted lines, with +% a dot gap that must be specified; actually the specified dash length or +% dot gap is a desired one; the actual length or gap is computed by integer +% division between the distance of the given points and the desired dash +% length or dot gap; when dashes are involved, this integer is tested in +% order to see if it is an odd number; if it's not, it is increased by +% unity. Then the actual dash length or dot gap is obtained by dividing the +% above distance by this number. +% +% Another vector $P_2-P_1$ is created by dividing it by this number; +% then, when dashes are involved, it is multiplied by two in order to have +% the increment from one dash to the next; finally the number of patterns +% is obtained by integer division of this number by 2 and increasing it +% by~1. +% A simple |\multiput| completes the job, but in order to use the various +% vectors and numbers within a group and to throw the result outside the +% group while restoring all the intermediate counters and registers, a +% service macro is created with an expanded definition and then this +% service macro is executed. +% Figure~\ref{fig:dashedlines} shows the effect of the slight changing +% of the dash length in order to maintain approximately the same dash-space +% pattern along the line, irrespective of the line length. +% The syntac is the following: +% \begin{flushleft} +% \cs{Dashline}\meta{\texttt{*}}\parg{first point}\parg{second point}\marg{dash length} +% \end{flushleft} +% where \meta{first point} contains the coordinates of the starting point +% and \meta{second point} those of the ending point; of course the +% \meta{dash length}, which equals the dash gap, is mandatory. The asterisk +% plays a specific role; in facts, if coordinates are specified in polar +% form, without the optional asterisk the dashed line is misplaced, while +% if the asterisk is specified, the whole object is pout in the proper +% position. On the opposite, if the coordinates are in cartesian form the +% \meta{first point} coordinates play the role they are supposed to do even +% without the asterisk. +% \begin{macrocode} +\ifx\Dashline\undefined + \def\Dashline{\@ifstar{\Dashline@@}{\Dashline@}} + + \def\Dashline@(#1)(#2)#3{% + \bgroup + \countdef\NumA3254\countdef\NumB3252\relax + \GetCoord(#1)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttA + \GetCoord(#2)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttB + \SubVect\V@ttA from\V@ttB to\V@ttC + \ModOfVect\V@ttC to\DlineMod + \DivideFN\DlineMod by#3 to\NumD + \NumA=\fpeval{trunc(\NumD,0)}\relax + \unless\ifodd\NumA\advance\NumA\@ne\fi + \NumB=\NumA \divide\NumB\tw@ + \DividE\DlineMod\p@ by\NumA\p@ to\D@shMod + \DividE\p@ by\NumA\p@ to \@tempa + \MultVect\V@ttC by\@tempa,0 to\V@ttB + \MultVect\V@ttB by 2,0 to\V@ttC + \advance\NumB\@ne + \edef\@mpt{\noexpand\egroup + \noexpand\multiput(\V@ttA)(\V@ttC){\number\NumB}% + {\noexpand\LIne(\V@ttB)}}% + \@mpt\ignorespaces}% + \let\Dline\Dashline + + \def\Dashline@@(#1)(#2)#3{\put(#1){\Dashline@(0,0)(#2){#3}}} +\fi +% \end{macrocode} +% +% A simpler |\Dotline| macro can draw a dotted line between two given +% points; the dots are rather small, therefore the inter dot distance is +% computed in such a way as to have the first and the last dot at the +% exact position of the dotted-line end-points; again the specified dot +% distance is nominal in the sense that it is recalculated in such a way +% that the first and last dots coincide with the line end points. The +% syntax is as follows: +%\begin{flushleft} +%\cs{Dotline}\meta{\texttt{*}}\parg{start point}\parg{end point}\marg{dot distance} +%\end{flushleft} +% \begin{macrocode} +\ifx\Dotline\undefined + \def\Dotline{\@ifstar{\Dotline@@}{\Dotline@}} + \def\Dotline@(#1)(#2)#3{% + \bgroup + \countdef\NumA 3254\relax \countdef\NumB 3255\relax + \GetCoord(#1)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttA + \GetCoord(#2)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttB + \SubVect\V@ttA from\V@ttB to\V@ttC + \ModOfVect\V@ttC to\DotlineMod + \DivideFN\DotlineMod by#3 to\NumD + \NumA=\fpeval{trunc(\NumD,0)}\relax + \DivVect\V@ttC by\NumA,0 to\V@ttB + \advance\NumA\@ne + \edef\@mpt{\noexpand\egroup + \noexpand\multiput(\V@ttA)(\V@ttB){\number\NumA}% + {\noexpand\makebox(0,0){\noexpand\circle*{0.5}}}}% + \@mpt\ignorespaces}% + + \def\Dotline@@(#1)(#2)#3{\put(#1){\Dotline@(0,0)(#2){#3}}}% +\fi +% \end{macrocode} +% +% Notice that vectors as complex numbers in their cartesian and polar forms +% always represent a point position referred to the origin of the axes; +% this is why in figures~\ref{fig:dashedlines} and~\ref{fig:dottedlines} +% the dashed and dotted line that depart from the lower right corner of +% the graph grid, and that use polar coordinates, have to be put at the +% proper position with the starred version of the commands that take care +% of the relative specification made with the polar coordinates. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Coordinate handling} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The new macro |\GetCoord| splits a vector (or complex number) +% specification into its components; in particular it distinguishes the +% polar from the cartesian form of the coordinates. The latter have the +% usual syntax \meta{x\texttt{,}y}, while the former have the syntax +% \meta{angle\texttt{:}radius}. The |\put| and |\multiput| commands are +% redefined to accept the same syntax; the whole work is done by +% |\SplitNod@| and its subsidiaries. +% +% Notice that package |eso-pic| uses |picture| macros in its definitions, +% but its original macro |\LenToUnit| is incompatible with this +% |\GetCoord| macro; its function is to translate real lengths into +% coefficients to be used as multipliers of the current |\unitlength|; in +% case that the |eso-pic| had been loaded, at the |\begin{document}| +% execution the |eso-pic| macro is redefined using the e-\TeX\ commands +% so as to make it compatible with these local macros.\footnote{Thanks to +% Franz-Joseph Berthold who was so kind to spot the bug.} +% \begin{macrocode} +\AtBeginDocument{\@ifpackageloaded{eso-pic}{% +\renewcommand\LenToUnit[1]{\strip@pt\dimexpr#1*\p@/\unitlength}}{}}% +% \end{macrocode} +% The above redefinition is delayed at |\AtBeginDocument| in order to have +% the possibility to check the the |eso-pic| package had actually been +% loaded. Nevertheless the code is defined here just because the origina +%l |eso-pic| macro was interfering with the algorithms of coordinate +% handling. +% +% But let us come to the real subject of this section. We define a +% |\GettCoord| macro that passes control to the service macro with the +% expanded arguments; expanding arguments allows to use macros to name +% points, instead of explicit coordinates; with this version of |curve2e| +% this facility is not fully exploited, but a creative user can use this +% feature. +% \begin{macrocode} +\def\GetCoord(#1)#2#3{% +\expandafter\SplitNod@\expandafter(#1)#2#3\ignorespaces} +\def\SplitNod@(#1)#2#3{\isnot@polar#1:!!(#1)#2#3}% +% \end{macrocode} +% The macro that detects the form of the coordinates is |\isnot@polar|; +% it examines the parameter syntax in order to see if it contains a +% colon; if it does, the coordinates are in polar form, otherwise they are +% in cartesian form. this macro uses delimited arguments, therefore low +% level definition syntax must be used. +% \begin{macrocode} +\def\isnot@polar#1:#2!!{\def\@tempOne{#2}\ifx\@tempOne\empty +\expandafter\@firstoftwo\else +\expandafter\@secondoftwo\fi +{\SplitNod@@}{\SplitPolar@@}} + +\def\SplitNod@@(#1,#2)#3#4{\edef#3{#1}\edef#4{#2}}% +\def\SplitPolar@@(#1:#2)#3#4{\DirFromAngle#1to\@DirA +\ScaleVect\@DirA by#2to\@DirA +\expandafter\SplitNod@@\expandafter(\@DirA)#3#4} + +\let\originalput\put +\def\put(#1){\bgroup\GetCoord(#1)\@tX\@tY +\edef\x{\noexpand\egroup\noexpand\originalput(\@tX,\@tY)}\x} + +\let\originalmultiput\multiput +\let\original@multiput\@multiput + +\long\def\@multiput(#1)#2#3{\bgroup\GetCoord(#1)\@mptX\@mptY +\edef\x{\noexpand\egroup\noexpand\original@multiput(\@mptX,\@mptY)}% +\x{#2}{#3}\ignorespaces} + +\gdef\multiput(#1)#2{\bgroup\GetCoord(#1)\@mptX\@mptY +\edef\x{\noexpand\egroup\noexpand\originalmultiput(\@mptX,\@mptY)}\x(}%) +% \end{macrocode} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Vectors} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The redefinitions and the new definitions for vectors are a little more +% complicated than with segments, because each vector is drawn as a filled +% contour; the original \texttt{pict2e} 2004 macro checks if the slopes +% are corresponding to the limitations specified by Lamport (integer three +% digit signed numbers) and sets up a transformation in order to make it +% possible to draw each vector as an horizontal left-to-right arrow and +% then to rotate it by its angle about its tail point; with |pict2e| 2009, +% possibly this redefinition of |\vector| is not necessary, but we do it +% as well and for the same reasons we had for redefining |\line|; actually +% there are two macros for tracing the contours that are eventually filled +% by the principal macro; each contour macro draws the vector with a +% \LaTeX\ or a PostScript styled arrow tip whose parameters are specified +% by default or may be taken from the parameters taken from the|PSTricks| +% package if this one is loaded before |pict2e|; in any case we did not +% change the contour drawing macros because if they are modified the same +% modification is passed on to the arrows drawn with the |curve2e| package +% redefinitions. +% +% Because of these features the redefinitions and the new macros are +% different from those used for straight lines. +% +% We start with the redefinition of |\vector| and we use the machinery for +% vectors (as complex numbers) we used for |\line|. +% \begin{macrocode} + \def\vector(#1)#2{% + \begingroup + \GetCoord(#1)\d@mX\d@mY + \@linelen#2\unitlength +% \end{macrocode} +% As in \texttt{pict2e} we avoid tracing vectors if the slope parameters +% are both zero. +% \begin{macrocode} + \ifdim\d@mX\p@=\z@\ifdim\d@mY\p@=\z@\@badlinearg\fi\fi +% \end{macrocode} +% But we check only for the positive nature of the $l_x$ component; if it +% is negative, we simply change sign instead of blocking the typesetting +% process. This is useful also for macros |\Vector|, |\VECTOR|, and +% |\VVECTOR| to be defined in a while. +% \begin{macrocode} + \ifdim\@linelen<\z@ \@linelen=-\@linelen\fi +% \end{macrocode} +% We now make a vector with the slope coefficients even if one or the +% other is zero and we determine its direction; the real and imaginary +% parts of the direction vector are also the values we need for the +% subsequent rotation. +% \begin{macrocode} + \MakeVectorFrom\d@mX\d@mY to\@Vect + \DirOfVect\@Vect to\Dir@Vect +% \end{macrocode} +% In order to be compatible with the original \texttt{pict2e} we need to +% transform the components of the vector direction in lengths with the +% specific names |\@xdim| and |\@ydim|^^A--------! Necessario? +% \begin{macrocode} + \YpartOfVect\Dir@Vect to\@ynum \@ydim=\@ynum\p@ + \XpartOfVect\Dir@Vect to\@xnum \@xdim=\@xnum\p@ +% \end{macrocode} +% If the vector is really sloping we need to scale the $l_x$ component in +% order to get the vector total length; we have to divide by the cosine of +% the vector inclination which is the real part of the vector direction. +% We use the floating point division function; since it yields a ``factor'' +% We directly use it to scale the length of the vector. I finally memorise +% the true vector length in the internal dimension |@tdB| +% \begin{macrocode} + \ifdim\d@mX\p@=\z@ + \else\ifdim\d@mY\p@=\z@ + \else + \edef\sc@lelen{\fpeval{1 / abs(\@xnum)}}\relax + \@linelen=\sc@lelen\@linelen + \fi + \fi + \@tdB=\@linelen +% \end{macrocode} +% The remaining code is definitely similar to that of \texttt{pict2e}; the +% real difference consists in the fact that the arrow is designed by itself +% without the stem; but it is placed at the vector end; therefore the first +% statement is just the transformation matrix used by the output driver to +% rotate the arrow tip and to displace it the right amount. But in order +% to draw only the arrow tip I have to set the |\@linelen| length to zero. +% \begin{macrocode} +\pIIe@concat\@xdim\@ydim{-\@ydim}\@xdim{\@xnum\@linelen}{\@ynum\@linelen}% + \@linelen\z@ + \pIIe@vector + \fillpath +% \end{macrocode} +% Now we can restore the stem length that must be shortened by the +% dimension of the arrow; by examining the documentation of \texttt{pict2e} +% we discover that we have to shorten it by an approximate amount of $AL$ +% (with the notations of \texttt{pict2e}, figs~10 and~11); the arrow tip +% parameters are stored in certain variables with which we can determine +% the amount of the stem shortening; if the stem was too short and the new +% length is negative, we avoid designing such a stem. +% \begin{macrocode} + \@linelen=\@tdB + \@tdA=\pIIe@FAW\@wholewidth + \@tdA=\pIIe@FAL\@tdA + \advance\@linelen-\@tdA + \ifdim\@linelen>\z@ + \moveto(0,0) + \pIIe@lineto{\@xnum\@linelen}{\@ynum\@linelen}% + \strokepath\fi + \endgroup} +% \end{macrocode} +% +% We define the macro that does not require the specification of the +% length or the $l_x$ length component; the way the new |\vector| macro +% works does not actually require this specification, because \TeX\ can +% compute the vector length, provided the two direction components are +% exactly the horizontal and vertical vector components. If the horizontal +% component is zero, the actual length must be specified as the vertical +% component. The object defined with |\Vector|, as well as |\vector|, +% must be put in place by means of a |\put| command. +% \begin{macrocode} +\def\Vector(#1){{% +\GetCoord(#1)\@tX\@tY +\ifdim\@tX\p@=\z@ + \vector(\@tX,\@tY){\@tY}% +\else + \vector(\@tX,\@tY){\@tX}% +\fi}} +% \end{macrocode} +% +% On the opposite the next macro specifies a vector by means of the +% coordinates of its end points; the first point is where the vector +% starts, and the second point is the arrow tip side. We need the +% difference of these two coordinates, because it represents the actual +% vector. +% \begin{macrocode} +\def\VECTOR(#1)(#2){\begingroup +\SubVect#1from#2to\@tempa +\expandafter\put\expandafter(#1){\expandafter\Vector\expandafter(\@tempa)}% +\endgroup\ignorespaces} +% \end{macrocode} +% +% The double tipped vector is built on the |\VECTOR| macro by simply +% drawing two vectors from the middle point of the double tipped vector. +% \begin{macrocode} +\def\VVECTOR(#1)(#2){{\SubVect#1from#2to\@tempb +\ScaleVect\@tempb by0.5to\@tempb +\AddVect\@tempb and#1to\@tempb +\VECTOR(\@tempb)(#2)\VECTOR(\@tempb)(#1)\ignorespaces}} +% \end{macrocode} +% +% The \texttt{pict2e} documentation says that if the vector length is zero +% the macro draws only the arrow tip; this may work with macro |\vector|, +% certainly not with |\Vector| and |\VECTOR|. This might be useful for +% adding an arrow tip to a circular arc. See examples in +% figure~\ref{fig:vectors}. +% +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Polylines and polygons} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We now define the polygonal line macro; its syntax is very simple: +% \begin{flushleft} +% \cs{polygonal}\oarg{join}\texttt{(}$P_0$\texttt{)(}$P_1$\texttt{)(}$P_2$)% +% \texttt{\dots(}$P_n$\texttt{)} +% \end{flushleft} +% Remember: |\polyline| has been incorporated into |pict2e| 2009, but we +% redefine it so as to allow an optional argument to specify the line join +% type. +% +% In order to write a recursive macro we need aliases for the parentheses; +% actually we need only the left parenthesis, but some editors complain +% about unmatched delimiters, so we define an alias also for the right parenthesis. +% \begin{macrocode} +\let\lp@r( \let\rp@r) +% \end{macrocode} +% The first call to |\polyline|, besides setting the line joints, examines +% the first point coordinates and moves the drawing position to this point; +% afterwards it looks for the second point coordinates; they start with a +% left parenthesis; if this is found the coordinates should be there, but +% if the left parenthesis is missing (possibly preceded by spaces that are +% ignored by the |\@ifnextchar| macro) then a warning message is output +% together with the line number where the missing parenthesis causes the +% warning: beware, this line number might point to several lines further on +% along the source file! In any case it's necessary to insert a +%|\@killglue|command, because |\polyline| refers to absolute coordinates, +% and not necessarily is put in position through a |\put| command that +% provides to eliminate any spurious spaces preceding this command. +% +% \begin{figure}[!hb] +% \begin{minipage}{0.55\textwidth} +%\begin{verbatim} +% \unitlength=0.07\hsize +% \begin{picture}(8,8)(-4,-4)\color{red} +% \polygon*(45:4)(135:4)(-135:4)(-45:4) +% \end{picture} +%\end{verbatim} +% \end{minipage} +% \hfill +% \begin{minipage}{0.4\textwidth}\centering +% \unitlength=0.07\hsize +% \begin{picture}(8,8)(-4,-4)\color{red} +% \polygon*(45:4)(135:4)(-135:4)(-45:4) +% \end{picture} +% \end{minipage} +% \caption{The code and the result of defining a polygon with its vertex +% polar coordinates}\label{fig:filled-polygon} +% \end{figure} +% +% In order to allow a specification for the joints of the various segments +% of a polyline it is necessary to allow for an optional parameter; +% the default is the bevel join. +% \begin{macrocode} +\renewcommand*\polyline[1][\beveljoin]{\p@lylin@[#1]} + +\def\p@lylin@[#1](#2){\@killglue#1\GetCoord(#2)\d@mX\d@mY + \pIIe@moveto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\p@lyline}{% + \PackageWarning{curve2e}% + {Polylines require at least two vertices!\MessageBreak + Control your polyline specification\MessageBreak}% + \ignorespaces}} + +% \end{macrocode} +% But if there is a second or further point coordinate, the recursive macro +% |\p@lyline| is called; it works on the next point and checks for a +% further point; if such a point exists it calls itself, otherwise it +% terminates the polygonal line by stroking it. +% \begin{macrocode} +\def\p@lyline(#1){\GetCoord(#1)\d@mX\d@mY + \pIIe@lineto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\p@lyline}{\strokepath\ignorespaces}} +% \end{macrocode} +% +% The same treatment must be done for the \cs{polygon} macros; we use the +% defining commands of package |xparse|, in order to use an optional +% asterisk; as it is usual with |picture| convex lines, the command with +% asterisk does not trace the contour, but fills the contour with the +% current color.The asterisk is tested at the beginning and, depending on +% its presence, a temporary switch is set to \texttt{true}; this being the +% case the contour is filled, otherwise it is simply stroked. +% \begin{macrocode} +\providecommand\polygon{} +\RenewDocumentCommand\polygon{s O{\beveljoin} }{\@killglue\begingroup +\IfBooleanTF{#1}{\@tempswatrue}{\@tempswafalse}% +\@polygon[#2]} + +\def\@polygon[#1](#2){\@killglue#1\GetCoord(#2)\d@mX\d@mY + \pIIe@moveto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\@@polygon}{% + \PackageWarning{curve2e}% + {Polygons require at least two vertices!\MessageBreak + Control your polygon specification\MessageBreak}% + \ignorespaces}} + + \def\@@polygon(#1){\GetCoord(#1)\d@mX\d@mY + \pIIe@lineto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\@@polygon}{\pIIe@closepath + \if@tempswa\pIIe@fillGraph\else\pIIe@strokeGraph\fi + \endgroup + \ignorespaces}} +% \end{macrocode} +% Now, for example, a filled polygon can be drawn using polar coordinates +% for its vertices; see figure~\ref{fig:filled-polygon} +% +% Remember; the polygon polar coordinates are relative to the origin of +% the local axes; therefore in order to position a polygon in a different +% position, it is necessary to do it through a |\put| command. + +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{The red service grid} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The next command is very useful for debugging while editing one's +% drawing; it draws a red grid with square meshes that are ten drawing +% units apart; there is no graduation along the grid, since it is supposed +% to be a debugging aid and the user should know what he/she is doing; +% nevertheless it is advisable to displace the grid by means of a |\put| +% command so that its grid lines coincide with the graph coordinates that +% are multiples of 10. Missing to do so the readings become cumbersome. +% The |\RoundUp| macro provides to increase the +% grid dimensions to integer multiples of ten. +% \begin{macrocode} +\def\GraphGrid(#1,#2){\bgroup\textcolor{red}{\linethickness{.1\p@}% +\RoundUp#1modulo10to\@GridWd \RoundUp#2modulo10to\@GridHt +\@tempcnta=\@GridWd \divide\@tempcnta10\relax \advance\@tempcnta\@ne +\multiput(0,0)(10,0){\@tempcnta}{\line(0,1){\@GridHt}}% +\@tempcnta=\@GridHt \divide\@tempcnta10\advance\@tempcnta\@ne +\multiput(0,0)(0,10){\@tempcnta}{\line(1,0){\@GridWd}}\thinlines}% +\egroup\ignorespaces} +% \end{macrocode} +% Rounding up is useful because also the grid margins fall on coordinates +% multiples of 10. It resorts to the |\Integer| macro that will be +% described in a while. +% \begin{macrocode} +\def\RoundUp#1modulo#2to#3{\expandafter\@tempcnta\Integer#1.??% +\count254\@tempcnta\divide\count254by#2\relax +\multiply\count254by#2\relax +\count252\@tempcnta\advance\count252-\count254 +\ifnum\count252>0\advance\count252-#2\relax +\advance\@tempcnta-\count252\fi\edef#3{\number\@tempcnta}\ignorespaces}% +% \end{macrocode} +% The |\Integer| macro takes a possibly fractional number whose decimal +% separator, if present, \textit{must} be the decimal point and uses the +% point as an argument delimiter. If one has the doubt that the number +% being passed to |\Integer| might be an integer, he/she should call the +% macro with a further point; if the argument is truly integer this point +% works as the delimiter of the integer part; if the argument being passed +% is fractional this extra point gets discarded as well as the fractional +% part of the number. +% \begin{macrocode} +\def\Integer#1.#2??{#1}% +% \end{macrocode} +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Math operations on fractional operands} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% This is not the place to complain about the fact that all programs of the +% \TeX\ system use only integer arithmetics; luckily enough, in 218 the +% package |xfp| was released: that package resorts in the background +% language \LaTeX\,3; this language now can compute fractional number +% operations coded in decimal digits and accepts also numbers written in +% the usual way in computer science, that is as a fractional, possibly +% signed, number followed by an expression that contains the exponent to +% 10 necessary to (ideally) move the fractional separator in one or the +% other direction according to the sign of the exponent of 10; in other +% words the L3 library for floating point calculations accepts such +% expressions as \texttt{123.456}, \texttt{0.12345e3}, and +% \texttt{12345e-3}, and any other equivalent expression. If the first +% number is integer, it assumes that the decimal separator is to the right +% of the rightmost digits of the digit string. +% +% Floating pint calculations may be done through the |\fpeval| L3 function +% with a very simple syntax: +% \begin{flushleft} +% \cs{fpeval}\marg{mathematical expression} +% \end{flushleft} +% where \meta{mathematica exression} can contain the usual algebraic +% operation sings, |= - * / ** ^| and the function names of the most +% common algebraic, trigonometric, and transcendental functions; for direct +% and inverse trigonometric functions it accepts arguments in radians and +% in sexagesimal degrees; it accepts the group of rounding/truncating +% operators; it can perform several kinds of comparisons; as to this date +% the todo list includes the direct and inverse hyperbolic functions. The +% mantissa length of the floating point operands amounts to 16 decimal +% digits. Further details may be read in the documentations of the |xfp| +% and |interface3| documents, just by typing into a command line window +% the command \texttt{texdoc \meta{document}}, where \meta{document} is +% just the name of the above named files without extension. +% +% Before the availability of the |xfp| package, it was necessary to fake +% fractional number computations by means of the native e-\TeX\ commands +% |\dimexpr|, i.e. to multiply each fractional number by the unit |\p@| +% (1\,pt) so as to get a length; operate un such lengths, and then +% stripping of the `pt' component from the result; very error prone and +% with less precision as the one that the modern decimal floating point +% calculations can do. Of course it is not so important to use fractional +% numbers with more that 5 or 6 fractional digits, because the other +% \TeX\ and \LaTeX\ macros cannot handle them, but it is very convenient +% to have simpler and more readable code. We therefore switched to the +% new floating point functionality, even if this maintains the |curve2e| +% functionality, but renders this package unusable with older \LaTeX\ +% kernel installations. It has already been explained that the input of +% |curve2e| gets aborted if the |xfp| package is not available. +% +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{The division macro} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% The most important macro is the division of two fractional numbers; we +% seek a macro that gets dividend and divisor as fractional numbers and +% saves their ratio in a macro; this is done in a simple way with the +% following code. +% \begin{macrocode} +\def\DividE#1by#2to#3{% + \edef#3{\fpeval{#1 / #2}}\relax +} +% \end{macrocode} +% In order to avoid problems with divisions by zero, or with numbers that +% yield results to large to be used as multipliers of lengths, it would be +% preferable that the above code be preceded or followed by some tests and +% possible messages. Actually we decided to avoid such tests and messages, +% because the internal L3 functions already provide some. This is what it +% was done in the previous versions of this package, when the |\fpeval| L3 +% function was not available. +% +% Notice that operands |#1| and |#2| may be integer numbers or fractional, +% or mixed numbers. They may be also dimensions, but while dimensions in +% printer points (72.27pt=1in) are handled as assumed, when different +% units are used, the length must be enclosed in parentheses: +%\begin{verbatim} +%\DividE(1mm)by(3mm) to\result +%\end{verbatim} +% yields correctly |\result=0.33333333|. Without parentheses the result is +% unpredictable. +% +% For backward compatibility we need an alias. +% \begin{macrocode} +\let\DivideFN\DividE +% \end{macrocode} +% +% We do the same in order to multiply two integer o fractional numbers +% held in the first two arguments and the third argument is a definable +% token that will hold the result of multiplication in the form of a +% fractional number, possibly with a non null fractional part; a null +% fractional part is stripped away +% \begin{macrocode} +\def\MultiplY#1by#2to#3{\edef#3{\fpeval{#1 * #2}}}\relax +\let\MultiplyFN\MultiplY +% \end{macrocode} +% but with multiplication it is better to avoid computations with lengths. +% +% The next macro uses the \verb|\strip@pt| \LaTeX\ kernel macro to get the +% numerical value of a measure in points. One has to call |\Numero| with +% a control sequence and a dimension; the dimension value in points is +% assigned to the control sequence. +% \begin{macrocode} +\unless\ifdefined\Numero + \def\Numero#1#2{\bgroup\dimen3254=#2\relax + \edef\x{\noexpand\egroup\noexpand\edef\noexpand#1{% + \strip@pt\dimen3254}}\x\ignorespaces}% +\fi +% \end{macrocode} +% The \verb|\ifdefined| primitive command is provided by the e-\TeX\ +% extension of the typesetting engine; the test does not create any hash +% table entry; it is a different way than the +% \verb|\ifx\csname ...\endcsname| test, +% because the latter first possibly creates a macro meaning \verb|\relax| +% then executes the test; therefore an undefined macro name is always +% defined to mean |\relax|. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Trigonometric functions} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We now start with trigonometric functions. In previous versions of this +% package we defined the macros |\SinOf|, |\CosOf| and |\TanOf| (|\CotOf| +% does not appear so essential) by means of the parametric +% formulas that require the knowledge of the tangent of the half angle. +% We wanted, and still want, to specify the angles in sexagesimal degrees, +% not in radians, so that accurate reductions to the main quadrants are +% possible. The formulas are +% \begin{eqnarray*} +% \sin\theta &=& \frac{2}{\cot x + \tan x}\\ +% \cos\theta &=& \frac{\cot x - \tan x}{\cot x + \tan x}\\ +% \tan\theta &=& \frac{2}{\cot x - \tan x}\\ +% \noalign{\hbox{where}} +% x &=& \theta/114.591559 +% \end{eqnarray*} +% is the half angle in degrees converted to radians. +% +% But now, in this new version, the availability of the floating point +% computations with the specific L3 library makes al the above superfluous; +% actually the above approach gave good results but it was cumbersome and +% limited by the fixed radix computations of the \TeX\ system programs. +% Matter of facts, we compared the results (with 6 fractional digits) the +% computations executed with the \texttt{sind} function name, in order to +% use the angles in degrees, and a table of trigonometric functions with +% the same number of fractional digits, and we di not find and difference, +% not even one unit on the sixth decimal digit. Probably the |\fpeval| +% computations, without rounding before the sixteenth significant digit, +% are much more accurate, but it is useless to have a better accuracy when +% the other \TeX\ and \LaTeX\ macros would not be able to exploit them. +% +% Having available such powerful instrument, even the tangent appears to +% be of little use for the kind of computations that are supposed to be +% required in this package. +% +% The codes for the computation of |\SinOf| and |\CosOf| of the angle in +% degrees is therefore the following +% \begin{macrocode} +\def\SinOf#1to#2{\edef#2{\fpeval{round(sind#1,6)}}}\relax +\def\CosOf#1to#2{\edef#2{\fpeval{round(cosd#1,6)}}}\relax +% \end{macrocode} +% +% +% As of today the anomaly (angle) of a complex number may not be necessary, +% but it might become useful in the future; therefore with macro +% \verb|\ArgOfVect| we calculate the four quadrant arctangent (in degrees) +% of the given vector taking into account the sings of the vector +% components. The |\ArgOfVect| macro receives on input a vector; +% from the signs of the horizontal and vertical components it determines +% the ratio and from this ratio the arctangent; but before doing this it +% tests the components in order to determine the quadrant of the vector +% tip; depending on signs it possibly adds what is necessary to determine +% the angle in the range $-180^\circ < \varphi \le +180^\circ$. If both +% components are zero, the angle is undefined, but for what concerns +% |curve2e| it is assigned the angle $0^circ$. +% \begin{macrocode} +\def\ArgOfVect#1to#2{\bgroup\GetCoord(#1){\t@X}{\t@Y}% +\def\s@gno{}% +\ifdim\t@X\p@=\z@ + \ifdim\t@Y\p@=\z@ + \def\ArcTan{0}% vettore nullo + \else + \def\ArcTan{90}% vettore verticale + \ifdim\t@Y\p@<\z@\def\ArcTan{-90}\fi + \fi +\else + \ifdim\t@Y\p@=\z@% vettore orizzontale + \ifdim\t@X\p@<\z@ + \def\ArcTan{180}% + \else + \def\ArcTan{0}% + \fi + \else % vettore qualsiasi + \edef\ArcTan{\fpeval{atand(\t@Y / \t@X)}}\relax + \ifdim\t@X\p@<\z@% vettore nei quadranti di sinistra + \ifdim\t@Y\p@<\z@ + \edef\ArcTan{\fpeval{\ArcTan - 180}}\relax + \else + \edef\ArcTan{\fpeval{\ArcTan + 180}}\relax + \fi + \fi + \fi +\fi +\edef\x{\noexpand\egroup\noexpand\edef\noexpand#2{\ArcTan}}% +\x\ignorespaces} +% \end{macrocode} +% +% It is worth examining the following table, where the angles of nine +% vectors $45^circ$ degrees from one another are computed from this macro. +% \begin{center} +% \begin{tabular}{l*9r} +% Vector &0,0 &1,0 &1,1 & 0,1 & -1,1& -1,0&-1,-1&0,-1&1,-1\\ +% Angle & 0 & 0 & 45 & 90 & 135 & 180 &-135 & -90& -45 +% \end{tabular} +% \end{center} +% Real computations with the |\ArgOfVect| macro produce those very numbers +% without the need of rounding; |\fpeval| produces all trimming of lagging +% zeros and rounding by itself. +% +% +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Arcs and curves preliminary information} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We would like to define now a macro for drawing circular arcs of any +% radius and any angular aperture; the macro should require the arc center, +% the arc starting point and the angular aperture. The arc has its +% reference point in its center, therefore it does not need to be put in +% place by the command |\put|; nevertheless if |\put| is used, it may +% displace the arc into another position. +% +% The command should have the following syntax: +% \begin{flushleft}\ttfamily +% \cs{Arc}(\meta{center})(\meta{starting point})\marg{angle} +% \end{flushleft} +% which is totally equivalent to: +% \begin{flushleft}\ttfamily +% \cs{put}(\meta{center})\marg{\upshape\cs{Arc}(0,0)(\meta{starting point})\marg{angle}} +% \end{flushleft} +% If the \meta{angle}, i.e. the arc angular aperture, is positive the arc +% runs counterclockwise from the starting point; clockwise if it's +% negative. +% Notice that since the \meta{starting point} is relative to the +% \meta{center} point, its polar coordinates are very convenient, since +% they become \parg{\meta{start angle}:\meta{radius}}, where the +% \meta{start angle} is relative to the arc center. Therefore you can think +% about a syntax such as this one: +%\begin{flushleft} +%\cs{Arc}\parg{\meta{center}}\parg{\normalfont{\itshape start angle}\texttt{:}{\itshape radius}}\marg{angle} +%\end{flushleft} +% +% The difference between the |pict2e| |\arc| definition consists in a very +% different syntax: +%\begin{flushleft} +%\cs{arc}\texttt{[}\meta{start angle}\texttt{,}\meta{end angle}\texttt{]}\marg{radius} +%\end{flushleft} +% and the center is assumed to be at the coordinate established with a +% required |\put| command; moreover the difference in specifying angles +% is that \meta{end angle} equals the sum of \meta{start angle} and +% \meta{angle}. With the definition of this |curve2e| package +% use of a |\put| command is not prohibited, but it may be used for fine +% tuning the arc position by means of a simple displacement; moreover the +% \meta{starting point} may be specified with polar coordinates (that are +% relative to the arc center). +% +% It's necessary to determine the end point and the control points of the +% Bézier spline(s) that make up the circular arc. +% +% The end point is obtained from the rotation of the starting point around +% the center; but the \texttt{pict2e} command |\pIIe@rotate| is such that +% the pivoting point appears to be non relocatable. +% It is therefore necessary to resort to low level \TeX\ commands and the +% defined trigonometric functions and a set of macros that operate on +% complex numbers used as vector roto-amplification operators. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Complex number macros} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% In this package \emph{complex number} is a vague phrase; it may be used +% in the mathematical sense of an ordered pair of real numbers; it can be +% viewed as a vector joining the origin of the coordinate axes to the +% coordinates indicated by the ordered pair; it can be interpreted as a +% roto-amplification operator that scales its operand and rotates it about +% a pivot point; besides the usual conventional representation used by the +% mathematicians where the ordered pair is enclosed in round parentheses +% (which is in perfect agreement with the standard code used by the +% |picture| environment) there is the other conventional representation +% used by the engineers that stresses the roto-amplification nature of a +% complex number: +%\[ +%(x, y) = x + \mathrm{j}y =M \mathrm{e}^{\mathrm{j}\theta} +%\] +% Even the imaginary unit is indicated with $\mathrm{i}$ by the +% mathematicians and with $\mathrm{j}$ by the engineers. In spite of these +% differences, these objects, the \emph{complex numbers}, are used without +% any problem by both mathematicians and engineers. +% +% The important point is that these objects can be summed, subtracted, +% multiplied, divided, raised to any power (integer, fractional, positive +% or negative), be the argument of transcendental functions according to +% rules that are agreed upon by everybody. We do not need all these +% properties, but we need some and we must create the suitable macros for +% doing some of these operations. +% +% In facts we need macros for summing, subtracting, multiplying, dividing +% complex numbers, for determining their directions (unit vectors); a unit +% vector is the complex number divided by its magnitude so that the result +% is the cartesian or polar form of the Euler's formula +% \[ +% \mathrm{e}^{\mathrm{j}\phi} = \cos\phi+\mathrm{j}\sin\phi +% \] +% +% The magnitude of a vector is determined by taking a ‘clever’ square root +% of a function of the real and the imaginary parts; see further on. +% +% It's better to represent each complex number with one control sequence; +% this implies frequent assembling and disassembling the pair of real +% numbers that make up a complex number. These real components are +% assembled into the defining control sequence as a couple of coordinates, +% i.e.\ two comma separated integer or fractional signed decimal numbers. +% +% For assembling two real numbers into a complex number we use the +% following elementary macro: +% \begin{macrocode} +\def\MakeVectorFrom#1#2to#3{\edef#3{#1,#2}\ignorespaces}% +% \end{macrocode} +% Another elementary macro copies a complex number into another one: +% \begin{macrocode} +\def\CopyVect#1to#2{\edef#2{#1}\ignorespaces}% +% \end{macrocode} +% The magnitude is determined with the macro |\ModOfVect| with delimited +% arguments; as usual it is assumed that the results are retrieved by means +% of control sequences, not used directly. +% +% In the preceding version of package |curve2e| the magnitude $M$ was +% determined by taking the moduli of the real and imaginary parts, by +% changing their signs if necessary; the larger component was +% then taken as the reference one so that, if $a$ is larger than $b$, the +% square root of the sum of their squares is computed as such: +% \[ +% M = \sqrt{a^2+b^2} = \vert a\vert\sqrt{1+(b/a)^2} +% \] +% In this way the radicand never exceeds 2 and it was quite easy to get its +% square root by means of the Newton iterative process; due to the +% quadratic convergence, five iterations were more than sufficient. When +% one of the components was zero, the Newton iterative process was skipped. +% With the availability of the |xfp| package and its floating point +% algorithms it is much easier to compute the magnitude of a complex +% number; since these algorithms allow to use very large numbers, it is +% not necessary to normalise the complex number components to the largest +% one; therefore the code is much simpler than the ne used for implementing +% the Newton method in the previous versions of this package. +% \begin{macrocode} +\def\ModOfVect#1to#2{\GetCoord(#1)\t@X\t@Y +\edef#2{\fpeval{sqrt(\t@X*\t@X + \t@Y*\t@Y)}}\relax +\ignorespaces}% +% \end{macrocode} +% +% Since the macro for determining the magnitude of a vector is available, +% we can now normalize the vector to its magnitude, therefore getting the +% Cartesian form of the direction vector. If by any chance the direction +% of the null vector is requested, the output is again the null vector, +% without normalization. +% \begin{macrocode} +\def\DirOfVect#1to#2{\GetCoord(#1)\t@X\t@Y +\ModOfVect#1to\@tempa +\unless\ifdim\@tempa\p@=\z@ + \DividE\t@X\p@ by\@tempa to\t@X + \DividE\t@Y\p@ by\@tempa to\t@Y +\fi +\MakeVectorFrom\t@X\t@Y to#2\ignorespaces}% +% \end{macrocode} +% +% A cumulative macro uses the above ones to determine with one call both +% the magnitude and the direction of a complex number. The first argument +% is the input complex number, the second its magnitude, and the third is +% again a complex number normalised to unit magnitude (unless the input was +% the null complex number); remember always that output quantities must be +% specified with control sequences to be used at a later time. +% \begin{macrocode} +\def\ModAndDirOfVect#1to#2and#3{% +\GetCoord(#1)\t@X\t@Y +\ModOfVect#1to#2% +\DirOfVect#1to#3\ignorespaces}% +% \end{macrocode} +% The next macro computes the magnitude and the direction of the difference +% of two complex numbers; the first input argument is the minuend, the +% second is the subtrahend; the output quantities are the third argument +% containing the magnitude of the difference and the fourth is the +% direction of the difference. +% The service macro |\SubVect| executes the difference of two complex +% numbers and is described further on. +% \begin{macrocode} +\def\DistanceAndDirOfVect#1minus#2to#3and#4{% +\SubVect#2from#1to\@tempa +\ModAndDirOfVect\@tempa to#3and#4\ignorespaces}% +% \end{macrocode} +% We now have two macros intended to fetch just the real or, respectively, +% the imaginary part of the input complex number. +% \begin{macrocode} +\def\XpartOfVect#1to#2{% +\GetCoord(#1)#2\@tempa\ignorespaces}% +% +\def\YpartOfVect#1to#2{% +\GetCoord(#1)\@tempa#2\ignorespaces}% +% \end{macrocode} +% With the next macro we create a direction vector (second argument) from a +% given angle (first argument, in degrees). +% \begin{macrocode} +\def\DirFromAngle#1to#2{% +\CosOf#1to\t@X +\SinOf#1to\t@Y +\MakeVectorFrom\t@X\t@Y to#2\ignorespaces}% +% \end{macrocode} +% +% Sometimes it is necessary to scale a vector by an arbitrary real factor; +% this implies scaling both the real and imaginary part of the input given vector. +% \begin{macrocode} +\def\ScaleVect#1by#2to#3{\GetCoord(#1)\t@X\t@Y +\edef\t@X{\fpeval{#2 * \t@X}}\relax +\edef\t@Y{\fpeval{#2 * \t@Y}}\relax +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +% \end{macrocode} +% Again, sometimes it is necessary to reverse the direction of rotation; +% this implies changing the sign of the imaginary part of a given complex +% number; this operation produces the complex conjugate of the given +% number. +% \begin{macrocode} +\def\ConjVect#1to#2{\GetCoord(#1)\t@X\t@Y +\edef\t@Y{-\t@Y}% +\MakeVectorFrom\t@X\t@Y to#2\ignorespaces}% +% \end{macrocode} +% +% With all the low level elementary operations we can now proceed to the +% definitions of the binary operations on complex numbers. We start with +% the addition: +% \begin{macrocode} +\def\AddVect#1and#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\edef\t@X{\fpeval{\tu@X + \td@X}}\relax +\edef\t@Y{\fpeval{\tu@Y + \td@Y}}\relax +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +% \end{macrocode} +% Then the subtraction: +% \begin{macrocode} +\def\SubVect#1from#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\edef\t@X{\fpeval{\td@X - \tu@X}}\relax +\edef\t@Y{\fpeval{\td@Y - \tu@Y}}\relax +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +% \end{macrocode} +% +% For the multiplication we need to split the operation according to the +% fact that we want to multiply by the second operand or by the complex +% conjugate of the second operand; it would be nice if we could use the +% usual postfixed asterisk notation for the complex conjugate, but we could +% not find a simple means for doing so; therefore we use the prefixed +% notation, that is I put the asterisk before the second operand. The first +% part of the multiplication macro just takes care of the multiplicand and +% then checks for the asterisk; if there is no asterisk it calls a second +% service macro that performs a regular complex multiplication, otherwise +% it calls a third service macro that executes the conjugate +% multiplication. +% \begin{macrocode} +\def\MultVect#1by{\@ifstar{\@ConjMultVect#1by}{\@MultVect#1by}}% +% +\def\@MultVect#1by#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\edef\t@X{\fpeval{\tu@X * \td@X - \tu@Y * \td@Y}}\relax +\edef\t@Y{\fpeval{\tu@Y * \td@X + \tu@X * \td@Y}}\relax +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +% +\def\@ConjMultVect#1by#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\edef\t@X{\fpeval{\tu@X * \td@X + \tu@Y * \td@Y}}\relax +\edef\t@Y{\fpeval{\tu@Y * \td@X - \tu@X * \td@Y}}\relax +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces} +% \end{macrocode} +% +% The division of two complex numbers implies scaling down the dividend +% by the magnitude of the divisor and by rotating the dividend scaled +% vector by the opposite direction of the divisor; therefore: +% \begin{macrocode} +\def\DivVect#1by#2to#3{\ModAndDirOfVect#2to\@Mod and\@Dir +\edef\@Mod{\fpeval{1 / \@Mod}}\relax +\ConjVect\@Dir to\@Dir +\ScaleVect#1by\@Mod to\@tempa +\MultVect\@tempa by\@Dir to#3\ignorespaces}% +% \end{macrocode} +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Arcs and curved vectors} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We are now in the position of really doing graphic work. +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Arcs} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We start with tracing a circular arc of arbitrary center, arbitrary +% starting point and arbitrary aperture; the first macro checks the +% aperture; if this is not zero it actually proceeds with the necessary +% computations, otherwise it does nothing. +% \begin{macrocode} +\def\Arc(#1)(#2)#3{\begingroup +\@tdA=#3\p@ +\unless\ifdim\@tdA=\z@ + \@Arc(#1)(#2)% +\fi +\endgroup\ignorespaces}% +% \end{macrocode} +% The aperture is already memorized in |\@tdA|; the |\@Arc| macro receives +% the center coordinates in the first argument and the coordinates of the +% starting point in the second argument. +% \begin{macrocode} +\def\@Arc(#1)(#2){% +\ifdim\@tdA>\z@ + \let\Segno+% +\else + \@tdA=-\@tdA \let\Segno-% +\fi +% \end{macrocode} +% The rotation angle sign is memorised in |\Segno| and |\@tdA| now contains +% the absolute value of the arc aperture. +% +% If the rotation angle is larger than $360^\circ$ a message is issued that +% informs the user that the angle will be reduced modulo $360^\circ$; this +% operation is performed by successive subtractions rather than with +% modular arithmetics on the assumption that in general one subtraction +% suffices. +% \begin{macrocode} +\Numero\@gradi\@tdA +\ifdim\@tdA>360\p@ + \PackageWarning{curve2e}{The arc aperture is \@gradi\space degrees + and gets reduced\MessageBreak% + to the range 0--360 taking the sign into consideration}% + \@whiledim\@tdA>360\p@\do{\advance\@tdA-360\p@}% +\fi +% \end{macrocode} +% Now the radius is determined and the drawing point is moved to the +% starting point. +% \begin{macrocode} +\SubVect#2from#1to\@V \ModOfVect\@V to\@Raggio +\CopyVect#2to\@pPun +\CopyVect#1to\@Cent \GetCoord(\@pPun)\@pPunX\@pPunY +% \end{macrocode} +% From now on it's better to define a new macro that will be used also in +% the subsequent macros that draw arcs; here we already have the starting +% point coordinates and the angle to draw the arc, therefore we just call +% the new macro, stroke the line and exit. +% \begin{macrocode} +\@@Arc\strokepath\ignorespaces}% +% \end{macrocode} +% And the new macro |\@@Arc| starts with moving the drawing point to the +% first% point and does everything needed for drawing the requested arc, +% except stroking it; I leave the \texttt{stroke} command to the completion +% of the calling macro and nobody forbids to use the |\@@Arc| macro for +% other purposes. +% \begin{macrocode} +\def\@@Arc{% +\pIIe@moveto{\@pPunX\unitlength}{\@pPunY\unitlength}% +% \end{macrocode} +% If the aperture is larger than $180^\circ$ it traces a semicircle in the +% right direction and correspondingly reduces the overall aperture. +% \begin{macrocode} +\ifdim\@tdA>180\p@ + \advance\@tdA-180\p@ + \Numero\@gradi\@tdA + \SubVect\@pPun from\@Cent to\@V + \AddVect\@V and\@Cent to\@sPun + \MultVect\@V by0,-1.3333333to\@V + \if\Segno-\ScaleVect\@V by-1to\@V\fi + \AddVect\@pPun and\@V to\@pcPun + \AddVect\@sPun and\@V to\@scPun + \GetCoord(\@pcPun)\@pcPunX\@pcPunY + \GetCoord(\@scPun)\@scPunX\@scPunY + \GetCoord(\@sPun)\@sPunX\@sPunY + \pIIe@curveto{\@pcPunX\unitlength}{\@pcPunY\unitlength}% + {\@scPunX\unitlength}{\@scPunY\unitlength}% + {\@sPunX\unitlength}{\@sPunY\unitlength}% + \CopyVect\@sPun to\@pPun +\fi +% \end{macrocode} +% If the remaining aperture is not zero it continues tracing the rest of +% the arc. Here we need the extrema of the arc and the coordinates of the +% control points of the Bézier cubic spline that traces the arc. The +% control points lay on the perpendicular to the vectors that join the arc +% center to the starting and end points respectively. +% +% With reference to figure~\ref{fig:arcspline}, the points $P_1$ and $P_2$ +% are the arc end-points; $C_1$ and $C_2$ are the Bézier-spline +% control-points; $P$ is the arc mid-point, that should be distant from +% the center of the arc the same as $P_1$ and $P_2$. +% Choosing a convenient orientation of the arc relative to the coordinate +% axes, the coordinates of these five points are: +%\begin{align*} +%P_1 &= (-R\sin\theta, 0)\\ +%P_2 &= (R\sin\theta, 0)\\ +%C_1 &= (-R\sin\theta+K\cos\theta, K\sin\theta)\\ +%C_2 &= (R\sin\theta-K\cos\theta, K\sin\theta)\\ +%P &= (0, R(1-\cos\theta)) +%\end{align*} +% The Bézier cubic spline interpolating the end and mid points is given by +% the parametric equation: +%\begin{equation*} +%P= P_1(1-t)^3 + C_1 3(1-t)^2t + C_2 3(1-t)t^2 + P_2t^3 +%\end{equation*} +% where the mid point is obtained for $t=0.5$; the four coefficients then +% become $1/8, 3/8, 3/8, 1/8$ and the only unknown remains $K$. Solving +% for $K$ we obtain the formula +% \begin{equation}\label{equ:corda} +% K= \frac{4}{3}\,\frac{1-\cos\theta}{\sin\theta}R +%= \frac{4}{3}\,\frac{1-\cos\theta}{\sin^2\theta}s +% \end{equation} +% where $\theta$ is half the arc aperture, $R$ is its radius, and $s$ is +% half the arc chord. +% \begin{macrocode} +\ifdim\@tdA>\z@ + \DirFromAngle\@gradi to\@Dir \if\Segno-\ConjVect\@Dir to\@Dir \fi + \SubVect\@Cent from\@pPun to\@V + \MultVect\@V by\@Dir to\@V + \AddVect\@Cent and\@V to\@sPun + \@tdA=.5\@tdA \Numero\@gradi\@tdA + \DirFromAngle\@gradi to\@Phimezzi + \GetCoord(\@Phimezzi)\@cosphimezzi\@sinphimezzi + \@tdB=1.3333333\p@ \@tdB=\@Raggio\@tdB + \@tdC=\p@ \advance\@tdC -\@cosphimezzi\p@ \Numero\@tempa\@tdC + \@tdB=\@tempa\@tdB + \DividE\@tdB by\@sinphimezzi\p@ to\@cZ + \ScaleVect\@Phimezzi by\@cZ to\@Phimezzi + \ConjVect\@Phimezzi to\@mPhimezzi + \if\Segno-% + \let\@tempa\@Phimezzi + \let\@Phimezzi\@mPhimezzi + \let\@mPhimezzi\@tempa + \fi + \SubVect\@sPun from\@pPun to\@V + \DirOfVect\@V to\@V + \MultVect\@Phimezzi by\@V to\@Phimezzi + \AddVect\@sPun and\@Phimezzi to\@scPun + \ScaleVect\@V by-1to\@V + \MultVect\@mPhimezzi by\@V to\@mPhimezzi + \AddVect\@pPun and\@mPhimezzi to\@pcPun + \GetCoord(\@pcPun)\@pcPunX\@pcPunY + \GetCoord(\@scPun)\@scPunX\@scPunY + \GetCoord(\@sPun)\@sPunX\@sPunY + \pIIe@curveto{\@pcPunX\unitlength}{\@pcPunY\unitlength}% + {\@scPunX\unitlength}{\@scPunY\unitlength}% + {\@sPunX\unitlength}{\@sPunY\unitlength}% +\fi} +% \end{macrocode} +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsubsection{Arc vectors} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We exploit much of the above definitions for the |\Arc| macro for drawing +% circular arcs with an arrow at one or both ends; the first macro +% |\VerctorArc| draws an arrow at the ending point of the arc; the second +% macro |\VectorARC| draws arrows at both ends; the arrows have the same +% shape as those for vectors; actually they are drawn by putting a vector +% of zero length at the proper arc end(s), therefore they are styled as +% traditional \LaTeX\ or PostScript arrows according to the specific +% option to the \texttt{pict2e} package. +% +% But the arc drawing done here shortens it so as not to overlap on the +% arrow(s); the only arrow (or both ones) are also lightly tilted in order +% to avoid the impression of a corner where the arc enters the arrow tip. +% +% All these operations require a lot of ``playing'' with vector +% directions, but even if the operations are numerous, they do not do +% anything else but: (a) determining the end point and its direction; +% (b) determining the arrow length as an angular quantity, i.e. the arc +% amplitude that must be subtracted from the total arc to be drawn; +% (c) the direction of the arrow should be corresponding to the tangent +% to the arc at the point where the arrow tip is attached; (d) tilting the +% arrow tip by half its angular amplitude; (e) determining the resulting +% position and direction of the arrow tip so as to draw a zero length +% vector; (f\/) possibly repeating the same procedure for the other end +% of the arc; (g) shortening the total arc angular amplitude by the +% amount of the arrow tip(s) already set, and finally (h) drawing the +% circular arc that joins the starting point to the final arrow or one +% arrow to the other +% one. +% +% The calling macros are very similar to the |\Arc| macro initial one: +% \begin{macrocode} +\def\VectorArc(#1)(#2)#3{\begingroup +\@tdA=#3\p@ \ifdim\@tdA=\z@\else + \@VArc(#1)(#2)% +\fi +\endgroup\ignorespaces}% +% +\def\VectorARC(#1)(#2)#3{\begingroup +\@tdA=#3\p@ +\ifdim\@tdA=\z@\else + \@VARC(#1)(#2)% +\fi +\endgroup\ignorespaces}% +% \end{macrocode} +% +% The single arrowed arc is defined with the following long macro where +% all the described operations are performed more or less in the described +% succession; probably the macro requires a little cleaning, but since it +% works fine we did not try to optimise it for time or number of tokens. +% The final part of the macro is almost identical to that of the plain arc; +% the beginning also is quite similar. The central part is dedicated to +% the positioning of the arrow tip and to the necessary calculations for +% determining the tip tilt and the reduction of the total arc length; pay +% attention that the arrow length, stored in |\@tdE| is a real length, +% while the radius stored in |\@Raggio| is just a multiple of the +% |\unitlength|, so that the division (that yields a good angular +% approximation to the arrow length as seen from the center of the arc) +% must be done with real lengths. The already defined |\@@Arc| macro +% actually draws the curved vector stem without stroking it. +% \begin{macrocode} +\def\@VArc(#1)(#2){% +\ifdim\@tdA>\z@ + \let\Segno+% +\else + \@tdA=-\@tdA \let\Segno-% +\fi \Numero\@gradi\@tdA +\ifdim\@tdA>360\p@ + \PackageWarning{curve2e}{The arc aperture is \@gradi\space degrees + and gets reduced\MessageBreak% + to the range 0--360 taking the sign into consideration}% + \@whiledim\@tdA>360\p@\do{\advance\@tdA-360\p@}% +\fi +\SubVect#1from#2to\@V \ModOfVect\@V to\@Raggio \CopyVect#2to\@pPun +\@tdE=\pIIe@FAW\@wholewidth \@tdE=\pIIe@FAL\@tdE +\DividE\@tdE by \@Raggio\unitlength to\DeltaGradi +\@tdD=\DeltaGradi\p@ +\@tdD=57.29578\@tdD \Numero\DeltaGradi\@tdD +\@tdD=\ifx\Segno--\fi\@gradi\p@ \Numero\@tempa\@tdD +\DirFromAngle\@tempa to\@Dir +\MultVect\@V by\@Dir to\@sPun +\edef\@tempA{\ifx\Segno-\m@ne\else\@ne\fi}% +\MultVect\@sPun by 0,\@tempA to\@vPun +\DirOfVect\@vPun to\@Dir +\AddVect\@sPun and #1 to \@sPun +\GetCoord(\@sPun)\@tdX\@tdY +\@tdD\ifx\Segno--\fi\DeltaGradi\p@ +\@tdD=.5\@tdD \Numero\DeltaGradi\@tdD +\DirFromAngle\DeltaGradi to\@Dird +\MultVect\@Dir by*\@Dird to\@Dir +\GetCoord(\@Dir)\@xnum\@ynum +\put(\@tdX,\@tdY){\vector(\@xnum,\@ynum){0}}% +\@tdE =\ifx\Segno--\fi\DeltaGradi\p@ +\advance\@tdA -\@tdE \Numero\@gradi\@tdA +\CopyVect#1to\@Cent \GetCoord(\@pPun)\@pPunX\@pPunY +\@@Arc +\strokepath\ignorespaces}% +% \end{macrocode} +% +% The macro for the arc terminated with arrow tips at both ends is again +% very similar, except it is necessary to repeat the arrow tip positioning +% also at the starting point. The |\@@Arc| macro draws the curved stem. +% \begin{macrocode} +\def\@VARC(#1)(#2){% +\ifdim\@tdA>\z@ + \let\Segno+% +\else + \@tdA=-\@tdA \let\Segno-% +\fi \Numero\@gradi\@tdA +\ifdim\@tdA>360\p@ + \PackageWarning{curve2e}{The arc aperture is \@gradi\space degrees + and gets reduced\MessageBreak% + to the range 0--360 taking the sign into consideration}% + \@whiledim\@tdA>360\p@\do{\advance\@tdA-360\p@}% +\fi +\SubVect#1from#2to\@V \ModOfVect\@V to\@Raggio \CopyVect#2to\@pPun +\@tdE=\pIIe@FAW\@wholewidth \@tdE=0.8\@tdE +\DividE\@tdE by \@Raggio\unitlength to\DeltaGradi +\@tdD=\DeltaGradi\p@ \@tdD=57.29578\@tdD \Numero\DeltaGradi\@tdD +\@tdD=\if\Segno--\fi\@gradi\p@ \Numero\@tempa\@tdD +\DirFromAngle\@tempa to\@Dir +\MultVect\@V by\@Dir to\@sPun% corrects the end point +\edef\@tempA{\if\Segno--\fi1}% +\MultVect\@sPun by 0,\@tempA to\@vPun +\DirOfVect\@vPun to\@Dir +\AddVect\@sPun and #1 to \@sPun +\GetCoord(\@sPun)\@tdX\@tdY +\@tdD\if\Segno--\fi\DeltaGradi\p@ +\@tdD=.5\@tdD \Numero\@tempB\@tdD +\DirFromAngle\@tempB to\@Dird +\MultVect\@Dir by*\@Dird to\@Dir +\GetCoord(\@Dir)\@xnum\@ynum +\put(\@tdX,\@tdY){\vector(\@xnum,\@ynum){0}}% end point arrowt ip +\@tdE =\DeltaGradi\p@ +\advance\@tdA -2\@tdE \Numero\@gradi\@tdA +\CopyVect#1to\@Cent \GetCoord(\@pPun)\@pPunX\@pPunY +\SubVect\@Cent from\@pPun to \@V +\edef\@tempa{\if\Segno-\else-\fi\@ne}% +\MultVect\@V by0,\@tempa to\@vPun +\@tdE\if\Segno--\fi\DeltaGradi\p@ +\Numero\@tempB{0.5\@tdE}% +\DirFromAngle\@tempB to\@Dird +\MultVect\@vPun by\@Dird to\@vPun% corrects the starting point +\DirOfVect\@vPun to\@Dir\GetCoord(\@Dir)\@xnum\@ynum +\put(\@pPunX,\@pPunY){\vector(\@xnum,\@ynum){0}}% starting point arrow tip +\edef\@tempa{\if\Segno--\fi\DeltaGradi}% +\DirFromAngle\@tempa to \@Dir +\SubVect\@Cent from\@pPun to\@V +\MultVect\@V by\@Dir to\@V +\AddVect\@Cent and\@V to\@pPun +\GetCoord(\@pPun)\@pPunX\@pPunY +\@@Arc +\strokepath\ignorespaces}% +% \end{macrocode} +% +% It must be understood that the curved vectors, the above circular arcs +% terminated with an arrow tip at one or both ends, have a nice appearance +% only if the arc radius is not too small, or, said in a different way, if +% the arrow tip angular width does not exceed a maximum of a dozen degrees +% (and this is probably already too much); the tip does not get curved as +% the arc is, therefore there is not a smooth transition from the curved +% stem and the straight arrow tip if this one is large in comparison to the arc radius. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{General curves} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The most used method to draw curved lines with computer programs is to +% connect several simple curved lines, general ``arcs'', one to another +% generally maintaining the same tangent at the junction. If the direction +% changes we are dealing with a cusp. +% +% The simple general arcs that are directly implemented in every program +% that display typeset documents, are those drawn with the parametric +% curves called \emph{Béźier splines}; given a sequence of points in the +% $x,y$ plane, say $P_0, P_1, P_2, p_3, \dots$ (represented as coordinate +% pairs, i.e. by complex numbers), the most common Bézier splines are the +% following ones: +% \begin{align} +% \mathcal{B}_1 &= P_0(1-t) + P_1t \label{equ:B-1} \\ +% \mathcal{B}_2 &= P_0(1-t)^2 + P_1 2(1-t)t + P_2t^2 \label{equ:B-2} \\ +% \mathcal{B}_3 &= P_0(1-t)^3 + P_1 3(1-t)^2t +P_2 3(1-t)t^2 +P_3t^3 +% \label{equ:B-3} +% \end{align} +% +% All these splines depend on parameter $t$; they have the property that +% for $t=0$ each line starts at the first point, while for $t=1$ they +% reach the last point; in each case the generic point $P$ on each curve +% takes off with a direction that points to the next point, while it +% lands on the destination point with a direction coming from the +% penultimate point; moreover, when $t$ varies from 0 to 1, the curve arc +% is completely contained within the convex hull formed by the polygon that +% has the spline points as vertices. +% +% Last but not least first order splines implement just straight lines +% and they are out of question for what concerns maxima, minima, +% inflection points and the like. Quadratic splines draw just +% parabolas, therefore they draw arcs that have the concavity just on one +% side of the path; therefore no inflection points. Cubic splines are +% extremely versatile and can draw lines with maxima, minima and inflection +% points. Virtually a multi-arc curve may be drawn by a set of cubic +% splines as well as a set of quadratic splines (fonts are a good example: +% Adobe Type~1 fonts have their contours described by cubic splines, while +% TrueType fonts have their contours described with quadratic splines; +% with a naked eye it is impossible to notice the difference). +% +% Each program that processes the file to be displayed is capable of +% drawing first order Bézier splines (segments) and third order Bézier +% splines, for no other reason, at least, because they have to draw vector +% fonts whose contours are described by Bézier splines; sometimes they +% have also the program commands to draw second order Bézier splines, but +% not always these machine code routines are available to the user for +% general use. For what concerns |pdftex|, |xetex| and |luatex|, they have +% the user commands for straight lines and cubic arcs. At least with +% |pdftex|, quadratic arcs must be simulated with a clever use of third +% order Bézier splines. +% +% Notice that \LaTeXe\ environment |picture| by itself is capable of +% drawing both cubic and quadratic Bézier splines as single arcs; but it +% resorts to ``poor man'' solutions. The |pict2e| package removes all the +% old limitations and implements the interface macros for sending the +% driver the necessary drawing information, including the transformation +% from typographical points (72.27\,pt/inch) to PostScript big points +% (72\,bp/inch). But for what concerns the quadratic spline it resorts to +% the clever use of a cubic spline. +% +% Therefore here we treat first the drawings that can be made with cubic +% splines; then we describe the approach to quadratic splines. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%\subsection{Cubic splines} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Now we define a macro for tracing a general, not necessarily circular, +% arc. This macro resorts to a general triplet of macros with which it is +% possible to draw almost anything. It traces a single Bézier spline from +% a first point where the tangent direction is specified to a second point +% where again it is specified the tangent direction. Actually this is a +% special (possibly useless) case where the general |\curve| macro of +% |pict2e| could do the same or a better job. In any case\dots +% \begin{macrocode} +\def\CurveBetween#1and#2WithDirs#3and#4{% + \StartCurveAt#1WithDir{#3}\relax + \CurveTo#2WithDir{#4}\CurveFinish\ignorespaces +}% +% \end{macrocode} +% +% Actually the above macro is a special case of concatenation of the +% triplet formed by macros |\StartCurve|, |\CurveTo| and|\CurveFinish|; +% the second macro can be repeated an arbitrary number of times. +% In any case the directions specified with the direction arguments, both +% here and with the more general macro|\Curve|, the angle between the +% indicated tangent and the arc chord may give raise to some little +% problems when they are very close to 90° in absolute value. Some control +% is exercised on these values, but some tests might fail if the angle +% derives from computations; this is a good place to use polar forms for +% the direction vectors. +% +% The first macro initializes the drawing and the third one strokes it; the +% real work is done by the second macro. The first macro initializes the +% drawing but also memorises the starting direction; the second macro +% traces the current Bézier arc reaching the destination point with the +% specified direction, but memorises this direction as the one with which +% to start the next arc. The overall curve is then always smooth because +% the various Bézier arcs join with continuous tangents. If a cusp is +% desired it is necessary to change the memorised direction at the end of +% the arc before the cusp and before the start of the next arc; this is +% better than stroking the curve before the cusp and then starting another +% curve, because the curve joining point at the cusp is not stroked with +% the same command, therefore we get two superimposed curve terminations. +% We therefore need another small macro |\ChangeDir| to perform this task. +% +% It is necessary to recall that the direction vectors point to the control +% points, but they do not define the control points themselves; they are +% just directions, or, even better, they are simply vectors with the +% desired direction; the macros themselves provide to the normalisation +% and memorization. +% +% The next desirable feature would be to design a macro that accepts +% optional node directions and computes the missing ones according to a +% suitable strategy. We can think of many such strategies, but none seems +% to be generally applicable, in the sense that one strategy might give +% good results, say, with sinusoids and another one, say, with cardioids, +% but neither one is suitable for both cases. +% +% For the moment we refrain from automatic direction computation, but we +% design the general macro as if directions were optional. +% +% Here we begin with the first initialising macro that receives with the +% first argument the starting point and with the second argument the +% direction of the tangent (not necessarily normalised to a unit vector) +% \begin{macrocode} +\def\StartCurveAt#1WithDir#2{% +\begingroup +\GetCoord(#1)\@tempa\@tempb +\CopyVect\@tempa,\@tempb to\@Pzero +\pIIe@moveto{\@tempa\unitlength}{\@tempb\unitlength}% +\GetCoord(#2)\@tempa\@tempb +\CopyVect\@tempa,\@tempb to\@Dzero +\DirOfVect\@Dzero to\@Dzero +\ignorespaces} +% \end{macrocode} +% And this re-initializes the direction to create a cusp: +% \begin{macrocode} +\def\ChangeDir<#1>{% +\GetCoord(#1)\@tempa\@tempb +\CopyVect\@tempa,\@tempb to\@Dzero +\DirOfVect\@Dzero to\@Dzero +\ignorespaces} +% \end{macrocode} +% +% The next macros are the finishing ones; the first strokes the whole +% curve, while the second fills the (closed) curve with the default color; +% both close the group that was opened with |\StartCurve|. The third macro +% is explained in a while; we anticipate it is functional to chose between +% the first two macros when a star is possibly used to switch between +% stroking and filling. +% \begin{macrocode} +\def\CurveFinish{\strokepath\endgroup\ignorespaces}% +\def\FillCurve{\fillpath\endgroup\ignorespaces} +\def\CurveEnd{\fillstroke\endgroup\ignorespaces} +% \end{macrocode} +% +% In order to draw the internal arcs it would be desirable to have a single +% macro that, given the destination point, computes the control points that +% produce a cubic Bézier spline that joins the starting point with the +% destination point in the best possible way. The problem is strongly ill +% defined and has an infinity of solutions; here we give two solutions: +% $(a)$ a supposedly smart one that resorts to osculating circles and +% requires only the direction at the destination point; and $(b)$ a less +% smart solution that requires the control points to be specified in a +% certain format. +% +% We start with solution $(b)$, |\CbezierTo|, the code of which is simpler +% than that of solution $(a)$; then we will produce the solution $(a)$, +% |\CurveTo|, that will become the main building block for a general path +% construction macro, |\Curve|. +% +% The “naïve” macro |\CBezierTo| simply uses the previous point direction +% saved in |\@Dzero| as a unit vector by the starting macro; specifies +% a destination point, the distance of the first control point from the +% starting point, the destination point direction that will save also for +% the next arc-drawing macro as a unit vector, and the distance of the +% second control point from the destination point along this last +% direction. Both distances must be positive possibly fractional numbers. +% The syntax therefore is the follwing: +%\begin{flushleft} +%\cs{CbezierTo}\meta{end +% point}|WithDir|\meta{direction}|AndDists|\meta{$K_0$}|And|\meta{$K_1$} +%\end{flushleft} +% where \meta{end point} is a vector macro or a comma separated pair of +% values; again \meta{direction} is another vector macro or a comma +% separated pair of values, that not necessarily indicate a unit vector, +% since the macro provides to normalise it to unity; \meta{$K_0$} and +% \meta{$K_1$} are the distances of the control points from their +% respective node points; they must be positive integers or fractional +% numbers. If \meta{$K_1$} is a number must be enclosed in curly braces, +% while if it is a macro name (containing the desired fractional or +% integer value) there is no need for braces. +% +% This macro uses the input information to use the internal |pict2e| macro +% |\pIIe@curveto| with the proper arguments, and to save the final +% direction into the same |\@Dzero| macro for successive use of other +% arc-drawing macros. +% \begin{macrocode} +\def\CbezierTo#1WithDir#2AndDists#3And#4{% +\GetCoord(#1)\@tX\@tY \MakeVectorFrom\@tX\@tY to\@Puno +\GetCoord(#2)\@tX\@tY \MakeVectorFrom\@tX\@tY to \@Duno +\DirOfVect\@Duno to\@Duno +\ScaleVect\@Dzero by#3to\@Czero \AddVect\@Pzero and\@Czero to\@Czero +\ScaleVect\@Duno by-#4to \@Cuno \AddVect\@Puno and\@Cuno to \@Cuno +\GetCoord(\@Czero)\@XCzero\@YCzero +\GetCoord(\@Cuno)\@XCuno\@YCuno +\GetCoord(\@Puno)\@XPuno\@YPuno +\pIIe@curveto{\@XCzero\unitlength}{\@YCzero\unitlength}% + {\@XCuno\unitlength}{\@YCuno\unitlength}% + {\@XPuno\unitlength}{\@YPuno\unitlength}% +\CopyVect\@Puno to\@Pzero +\CopyVect\@Duno to\@Dzero +\ignorespaces}% +% \end{macrocode} +% +% With this building block it is not difficult to set up a macro that draws +% a Bézier arc between two given points, similarly to the other macro +% |\CurveBetween| previously described and defined here: +% +% \begin{macrocode} +\def\CbezierBetween#1And#2WithDirs#3And#4UsingDists#5And#6{% +\StartCurveAt#1WithDir{#3}\relax +\CbezierTo#2WithDir#4AndDists#5And{#6}\CurveFinish} +% \end{macrocode} + +% +% An example of use is shown in figure~\ref{fig:Cbezier}; notice that the +% tangents at the end points are the same for the black curve drawn with +% |\CurveBetween| and the five red curves drawn with |\CbezierBetween|; the +% five red curves differ only for the distance of their control point $C_0$ +% from the starting point; the differences are remarkable and the topmost +% curve even presents a slight inflection close to the end point. These +% effects cannot be obtained with the ``smarter'' macro |\CurveBetween|. +% But certainly this simpler macro is more difficult to use because the +% distances of the control points are difficult to estimate and require a +% number of cut-and-try experiments. +% +% +% The ``smarter'' curve macro comes next; it is supposed to determine the +% control points for joining the previous point (initial node) with the +% specified direction to the next point with another specified direction +% (final node). +% Since the control points are along the specified directions, it is +% necessary to determine the distances from the adjacent curve nodes. This +% must work correctly even if nodes and directions imply an inflection +% point somewhere along the arc. +% +% The strategy we devised consists in determining each control point as if +% it were the control point of a circular arc, precisely an arc of an +% osculating circle, i.e. a circle tangent to the curve at that node. The +% ambiguity of the stated problem may be solved by establishing that the +% chord of the osculating circle has the same direction as the chord of the +% arc being drawn, and that the curve chord is divided into two equal parts +% each of which should be interpreted as half the chord of the osculating +% circle. +% +% This makes the algorithm a little rigid; sometimes the path drawn is very +% pleasant, while in other circumstances the determined curvatures are too +% large or too small. We therefore add some optional information that lets +% us have some control over the curvatures; the idea is based on the +% concept of \emph{tension}, similar but not identical to the one used in +% the drawing programs \MF\ and \MP. We add to the direction information, +% with which the control nodes of the osculating circle arcs are +% determined, a scaling factor that should be intuitively related to the +% tension of the arc (actually, since the tension of the ‘rope’ is high +% when this parameter is low, probably a name such as ‘looseness’ would be +% better suited): the smaller this number, the closer the arc resembles +% a straight line as a rope subjected to a high tension; value zero is +% allowed, while a value of 4 is close to ``infinity'' and turns a quarter +% circle into a line with an unusual loop; a value of 2 turns a quarter +% circle almost into a polygonal line with rounded corner. Therefore these +% tension factors should be used only for fine tuning the arcs, not when +% a path is drawn for the first time. +% +% We devised a syntax for specifying direction and tensions: +%\begin{flushleft} +% \meta{direction\texttt{\upshape;}tension factors} +%\end{flushleft} +% where \emph{direction} contains a pair of fractional number that not +% necessarily refer to the components of a unit vector direction, but +% simply to a vector with the desired orientation (polar form is OK); the +% information contained from the semicolon (included) to the rest of the +% specification is optional; if it is present, the \emph{tension factors} +% is simply a comma separated pair of fractional or integer numbers that +% represent respectively the tension at the starting or the ending node of +% a path arc. +% +% We therefore need a macro to extract the mandatory and optional parts: +% \begin{macrocode} +\def\@isTension#1;#2!!{\def\@tempA{#1}% +\def\@tempB{#2}\unless\ifx\@tempB\empty\strip@semicolon#2\fi} + +\def\strip@semicolon#1;{\def\@tempB{#1}} +% \end{macrocode} +% By changing the tension values we can achieve different results: see +% figure~\ref{fig:tensions}. +% +% We use the formula we got for arcs~\eqref{equ:corda}, where the half +% chord is indicated with $s$, and we derive the necessary distances: +%\begin{subequations}\label{equ:Kzero-Kuno} +%\begin{align} +%K_0 &= \frac{4}{3} s\frac{1-\cos\theta_0}{\sin^2\theta_0}\\ +%K_1 &=\frac{4}{3}s\frac{1-\cos\theta_1}{\sin^2\theta_1} +%\end{align} +%\end{subequations} +% +% We therefore start with getting the points and directions and calculating +% the chord and its direction: +% \begin{macrocode} +\def\CurveTo#1WithDir#2{% +\def\@Tuno{1}\def\@Tzero{1}\relax +\edef\@Puno{#1}\@isTension#2;!!% +\expandafter\DirOfVect\@tempA to\@Duno +\bgroup\unless\ifx\@tempB\empty\GetCoord(\@tempB)\@Tzero\@Tuno\fi +\DistanceAndDirOfVect\@Puno minus\@Pzero to\@Chord and\@DirChord +% \end{macrocode} +% Then we rotate everything about the starting point so as to bring the +% chord on the real axis +% \begin{macrocode} +\MultVect\@Dzero by*\@DirChord to \@Dpzero +\MultVect\@Duno by*\@DirChord to \@Dpuno +\GetCoord(\@Dpzero)\@DXpzero\@DYpzero +\GetCoord(\@Dpuno)\@DXpuno\@DYpuno +\DivideFN\@Chord by2 to\@semichord +% \end{macrocode} +% The chord needs not be actually rotated because it suffices its length +% along the real axis; the chord length is memorised in |\@Chord| and +% its half is saved in |\@semichord|. +% +% We now examine the various degenerate cases, when either tangent is +% perpendicular or parallel to the chord. Notice that we are calculating +% the distances of the control points from the adjacent nodes using the +% half chord length, not the full length. We also distinguish between the +% computations relative to the arc starting point and those relative to +% the end point. +% +% \begin{macrocode} +\ifdim\@DXpzero\p@=\z@ + \@tdA=1.333333\p@ + \Numero\@KCzero{\@semichord\@tdA}% +\fi +\ifdim\@DYpzero\p@=\z@ + \@tdA=1.333333\p@ + \Numero\@Kpzero{\@semichord\@tdA}% +\fi +% \end{macrocode} +% The distances we are looking for are positive generally fractional +% numbers; so if the components are negative, we take the absolute values. +% Eventually we determine the absolute control point coordinates. +% \begin{macrocode} +\unless\ifdim\@DXpzero\p@=\z@ + \unless\ifdim\@DYpzero\p@=\z@ + \edef\@CosDzero{\ifdim\@DXpzero\p@<\z@ -\fi\@DXpzero}% + \edef\@SinDzero{\ifdim\@DYpzero\p@<\z@ -\fi\@DYpzero}% + \@tdA=\@semichord\p@ \@tdA=1.333333\@tdA + \DividE\@tdA by\@SinDzero\p@ to \@KCzero + \@tdA=\dimexpr(\p@-\@CosDzero\p@)\relax + \DividE\@KCzero\@tdA by\@SinDzero\p@ to \@KCzero + \fi +\fi +\MultiplyFN\@KCzero by \@Tzero to \@KCzero +\ScaleVect\@Dzero by\@KCzero to\@CPzero +\AddVect\@Pzero and\@CPzero to\@CPzero +% \end{macrocode} +% We now repeat the calculations for the arc end point, taking into +% consideration that the end point direction points outwards, so that in +% computing the end point control point we have to take this fact into +% consideration by using a negative sign for the distance; in this way +% the displacement of the control point from the end point takes place +% in a backwards direction. +% \begin{macrocode} +\ifdim\@DXpuno\p@=\z@ + \@tdA=-1.333333\p@ + \Numero\@KCuno{\@semichord\@tdA}% +\fi +\ifdim\@DYpuno\p@=\z@ + \@tdA=-1.333333\p@ + \Numero\@KCuno{\@semichord\@tdA}% +\fi +\unless\ifdim\@DXpuno\p@=\z@ + \unless\ifdim\@DYpuno\p@=\z@ + \edef\@CosDuno{\ifdim\@DXpuno\p@<\z@ -\fi\@DXpuno}% + \edef\@SinDuno{\ifdim\@DYpuno\p@<\z@ -\fi\@DYpuno}% + \@tdA=\@semichord\p@ \@tdA=-1.333333\@tdA + \DividE\@tdA by \@SinDuno\p@ to \@KCuno + \@tdA=\dimexpr(\p@-\@CosDuno\p@)\relax + \DividE\@KCuno\@tdA by\@SinDuno\p@ to \@KCuno + \fi +\fi +\MultiplyFN\@KCuno by \@Tuno to \@KCuno +\ScaleVect\@Duno by\@KCuno to\@CPuno +\AddVect\@Puno and\@CPuno to\@CPuno +% \end{macrocode} +% Now we have the four points and we can instruct the internal +% \texttt{pict2e} macros to do the path drawing. +% \begin{macrocode} +\GetCoord(\@Puno)\@XPuno\@YPuno +\GetCoord(\@CPzero)\@XCPzero\@YCPzero +\GetCoord(\@CPuno)\@XCPuno\@YCPuno +\pIIe@curveto{\@XCPzero\unitlength}{\@YCPzero\unitlength}% + {\@XCPuno\unitlength}{\@YCPuno\unitlength}% + {\@XPuno\unitlength}{\@YPuno\unitlength}\egroup +% \end{macrocode} +% It does not have to stroke the curve because other Bézier splines might +% still be added to the path. On the opposite it memorises the final point +% as the initial point of the next spline +% \begin{macrocode} +\CopyVect\@Puno to\@Pzero +\CopyVect\@Duno to\@Dzero +\ignorespaces}% +% \end{macrocode} +% +% +% We finally define the overall |\Curve| macro that has two flavours: +% starred and unstarred; the former fills the curve path with the locally +% selected color, while the latter just strokes the path. Both recursively +% examine an arbitrary list of nodes and directions; node coordinates are +% grouped within regular parentheses while direction components are grouped within angle brackets. The first call of the macro initialises the drawing +% process and checks for the next node and direction; if a second node is +% missing, it issues a warning message and does not draw anything. It does +% not check for a change in direction, because it would be meaningless at +% the beginning of a curve. The second macro defines the path to the next +% point and checks for another node; if the next list item is a square +% bracket delimited argument, it interprets it as a change of direction, +% while if it is another parenthesis delimited argument it interprets it as +% a new node-direction specification; if the node and direction list is +% terminated, it issues the stroking or filling command through +% |\CurveEnd|, and exits the recursive process. The |\CurveEnd| control +% sequence has a different meaning depending on the fact that the main +% macro was starred or unstarred. The |@ChangeDir| macro is just an +% interface to execute the regular |\ChangeDir| macro, but also for +% recursing again by recalling |\@Curve|. +% \begin{macrocode} +\def\Curve{\@ifstar{\let\fillstroke\fillpath\Curve@}% +{\let\fillstroke\strokepath\Curve@}} + +\def\Curve@(#1)<#2>{% + \StartCurveAt#1WithDir{#2}% + \@ifnextchar\lp@r\@Curve{% + \PackageWarning{curve2e}{% + Curve specifications must contain at least two nodes!\Messagebreak + Please, control your \string\Curve\space specifications\MessageBreak}}} +\def\@Curve(#1)<#2>{% + \CurveTo#1WithDir{#2}% + \@ifnextchar\lp@r\@Curve{% + \@ifnextchar[\@ChangeDir\CurveEnd}} +\def\@ChangeDir[#1]{\ChangeDir<#1>\@Curve} +% \end{macrocode} +% +% As a concluding remark, please notice that the |\Curve| macro is +% certainly the most comfortable to use, but it is sort of frozen in its +% possibilities. The user may certainly use the |\StartCurve|, |\CurveTo|, +% |\ChangeDir|, and |\CurveFinish| or |\FillCurve| for a more versatile +% set of drawing macros; evidently nobody forbids to exploit the full power +% of the |\cbezier| original macro for cubic splines; we made available +% macros |\CbezierTo| and the isolated arc macro |\CbezierBetween| in order +% to use the general internal cubic Bézier splines in a more comfortable +% way. +% +% As it can be seen in figure~\ref{fig:sinewave} the two diagrams should +% approximately represent a sine wave. With Bézier curves, that resort on +% polynomials, it is impossible to represent a transcendental function, but +% it is only possible to approximate it. It is evident that the +% approximation obtained with full control on the control points requires +% less arcs and it is more accurate than the approximation obtained with +% the recursive |\Curve| macro; this macro requires almost two times as +% many pieces of information in order to minimise the effects of the lack +% of control on the control points, and even with this added information +% the macro approaches the sine wave with less accuracy. At the same time +% for many applications the |\Curve| recursive macro proves to be much +% easier to use than with single arcs drawn with the |\CbezierBetween| +% macro. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Quadratic splines} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% We want to create a recursive macro with the same properties as the above +% described |\Curve| macro, but that uses quadratic splines; we call it +% |\Qurve| so that the initial macro name letter reminds us of the nature +% of the splines being used. For the rest they have an almost identical +% syntax; with quadratic spline it is not possible to specify the distance +% of the control points from the extrema, since quadratic spline have just +% one control point that must lay at the intersection of the two tangent +% directions therefore with quadratic splines the tangents at each point +% cannot have the optional part that starts with a semicolon. The syntax, +% therefore, is just: +%\begin{flushleft} +%\cs{Qurve}\parg{first point}\aarg{direction}...\parg{any point}\aarg{direction}...\parg{last point}\aarg{direction} +%\end{flushleft} +% As with |\Curve|, also with |\Qurve| there is no limitation on the number +% of points, except for the computer memory size; it is advisable not to +% use many arcs otherwise it might become very difficult to find errors. +% +% The first macros that set up the recursion are very similar to those we +% wrote for |\Curve|: +% \begin{macrocode} +\def\Qurve{\@ifstar{\let\fillstroke\fillpath\Qurve@}% +{\let\fillstroke\strokepath\Qurve@}} + +\def\Qurve@(#1)<#2>{% + \StartCurveAt#1WithDir{#2}% + \@ifnextchar\lp@r\@Qurve{% + \PackageWarning{curve2e}{% + Quadratic curve specifications must contain at least + two nodes!\Messagebreak + Please, control your Qurve specifications\MessageBreak}}}% + +\def\@Qurve(#1)<#2>{\QurveTo#1WithDir{#2}% + \@ifnextchar\lp@r\@Qurve{% + \@ifnextchar[\@ChangeQDir\CurveEnd}}% + +\def\@ChangeQDir[#1]{\ChangeDir<#1>\@Qurve}% +% \end{macrocode} +% +% Notice that in case of long paths it might be better to use the single +% macros |\StartCurveAt|, |\QurveTo|, |\ChangeDir| and |\CurveFinish| +% (or |\FillCurve|), with their respective syntax, in such a way that a +% long list % of node-direction specifications passed to |\Qurve| may be +% split into shorter input lines in order to edit the input data in a more +% comfortable way. +% +% +% The macro that does everything is |\QurveTo|. it starts with reading its +% arguments received through the calling macro |\@Qurve| +% \begin{macrocode} +\def\QurveTo#1WithDir#2{% +\edef\@Puno{#1}\DirOfVect#2to\@Duno\bgroup +\DistanceAndDirOfVect\@Puno minus\@Pzero to\@Chord and\@DirChord +% \end{macrocode} +% It verifies if |\@Dpzero| and |\@Dpuno|, the directions at the two +% extrema of the arc, are parallel or anti-parallel by taking their +% ``scalar'' product (|\@Dpzero| times |\@Dpuno*|); if the imaginary +% component of the scalar product vanishes the two directions are +% parallel; in this case we produce an error message, but we continue by +% skipping this arc destination point; evidently the drawing will not be +% the desired one, but the job should not abort. +% \begin{macrocode} +\MultVect\@Dzero by*\@Duno to \@Scalar +\YpartOfVect\@Scalar to \@YScalar +\ifdim\@YScalar\p@=\z@ +\PackageWarning{curve2e}% + {Quadratic Bezier arcs cannot have their starting\MessageBreak + and ending directions parallel or antiparallel with\MessageBreak + each other. This arc is skipped and replaced with + a dotted line.\MessageBreak}% + \Dotline(\@Pzero)(\@Puno){2}\relax +\else +% \end{macrocode} +% Otherwise we rotate everything about the starting point so as to bring +% the chord on the real axis; we get also the components of the two +% directions that, we should remember, are unit vectors, not generic +% vectors, although the user can use the vector specifications that are +% more understandable to him/her: +% \begin{macrocode} +\MultVect\@Dzero by*\@DirChord to \@Dpzero +\MultVect\@Duno by*\@DirChord to \@Dpuno +\GetCoord(\@Dpzero)\@DXpzero\@DYpzero +\GetCoord(\@Dpuno)\@DXpuno\@DYpuno +% \end{macrocode} +% We check if the two directions point to the same half plane; this implies +% that these rotated directions point to different sides of the chord +% vector; all this is equivalent that the two direction Y components have +% opposite signs, so that their product is strictly negative, while the two +% X components product is not negative. +% \begin{macrocode} +\MultiplyFN\@DXpzero by\@DXpuno to\@XXD +\MultiplyFN\@DYpzero by\@DYpuno to\@YYD +\unless\ifdim\@YYD\p@<\z@\ifdim\@XXD\p@<\z@ +\PackageWarning{curve2e}% + {Quadratic Bezier arcs cannot have inflection points\MessageBreak + Therefore the tangents to the starting and ending arc\MessageBreak + points cannot be directed to the same half plane.\MessageBreak + This arc is skipped and replaced by a dotted line\MessageBreak}% + \Dotline(\@Pzero)(\@Puno){2}\fi +\else +% \end{macrocode} +% +% After these tests we should be in a ``normal'' situation. We first copy +% the expanded input information into new macros that have more explicit +% names: macros stating wit `S' denote the sine of the direction angle, +% while those starting with `C' denote the cosine of that angle. We will +% use these expanded definitions as we know we are working with the actual +% values. These directions are those relative to the arc chord. +% \begin{macrocode} +\edef\@CDzero{\@DXpzero}\relax +\edef\@SDzero{\@DYpzero}\relax +\edef\@CDuno{\@DXpuno}\relax +\edef\@SDuno{\@DYpuno}\relax +% \end{macrocode} +% Suppose we write the parametric equations of a straight line that departs +% from the beginning of the chord with direction angle $\phi_0$ and the +% corresponding equation of the straight line departing from the end of the +% chord (of length $c$) with direction angle $\phi_1$. We have to find the +% coordinates of the intersection point of these two straight lines. +%\begin{subequations} +%\begin{align} +% t \cos\phi_0 - s \cos\phi_1 &= c\\ +% t \sin\phi_0 - s \sin\phi_1 &= 0 +%\end{align} +%\end{subequations} +% The parameters $t$ and $s$ are just the running parameters; we have +% to solve those simultaneous equations in the unknown variables $t$ and +% $s$; these values let us compute the coordinates of the intersection +% point: +%\begin{subequations}\begin{align} +% X_C &=\dfrac{c\cos\phi_0\sin\phi_1}{\sin\phi_0\cos\phi_1 - \cos\phi_0\sin\phi_1} \\ +% Y_C &=\dfrac{c\sin\phi_0\sin\phi_1}{\sin\phi_0\cos\phi_1 - \cos\phi_0\sin\phi_1} +%\end{align}\end{subequations} +% +% Having performed the previous tests we are sure that the denominator is +% not vanishing (direction are not parallel or anti-parallel) and that it +% lays at the same side as the direction with angle $\phi_0$ with respect +% to the chord. +% +% The coding then goes on like this: +% \begin{macrocode} +\MultiplyFN\@SDzero by\@CDuno to\@tempA +\MultiplyFN\@SDuno by\@CDzero to\@tempB +\edef\@tempA{\strip@pt\dimexpr\@tempA\p@-\@tempB\p@}\relax +\@tdA=\@SDuno\p@ \@tdB=\@Chord\p@ \@tdC=\@tempA\p@ +\edef\@tempC{\strip@pt\dimexpr \@tdA*\@tdB/\@tdC}\relax +\MultiplyFN\@tempC by\@CDzero to \@XC +\MultiplyFN\@tempC by\@SDzero to \@YC +\ModOfVect\@XC,\@YC to\@KC +% \end{macrocode} +% Now we have the coordinates and the module of the intersection point +% vector taking into account the rotation of the real axis; getting back +% to the original coordinates before rotation, we get: +% \begin{macrocode} +\ScaleVect\@Dzero by\@KC to\@CP +\AddVect\@Pzero and\@CP to\@CP +\GetCoord(\@Pzero)\@XPzero\@YPzero +\GetCoord(\@Puno)\@XPuno\@YPuno +\GetCoord(\@CP)\@XCP\@YCP +% \end{macrocode} +% We have now the coordinates of the two extrema point of the quadratic arc +% and of the control point. Keeping in mind that the symbols $P_0$, $P_1$ +% and $C$ denote geometrical points but also their coordinates as ordered +% pairs of real numbers (i.e. they are complex numbers) we have to +% determine the parameters of a cubic spline that with suitable values +% get simplifications in its parametric equation so that it becomes a +% second degree function instead of a third degree one. It is possible, +% in spite of the fact the it appears impossible that e cubic form becomes +% a quadratic one; we should determine the values of $P_a$ and $P_b$ such +% that: +%\[ +% P_0(1-t)^3 +3P_a(1-t)^2t +3P_b(1-t)t^2 +P_1t^3 +%\] +% is equivalent to +%\[ +% P_0(1-t)^2 + 2C(1-t)t + P_1t^2 +%\] +% It turns out that the solution is given by +%\begin{equation} +% P_a= C+(P_0-C)/3 \qquad \text{and}\qquad P_b = C+(P_1- C)/3 +%\label{equ:spline3} +%\end{equation} +% +% The transformations implied by equations~\eqref{equ:spline3} are +% performed by the following macros already available from the |pict2e| +% package; we use them here with the actual arguments used for this task: +% \begin{macrocode} +\@ovxx=\@XPzero\unitlength \@ovyy=\@YPzero\unitlength +\@ovdx=\@XCP\unitlength \@ovdy=\@YCP\unitlength +\@xdim=\@XPuno\unitlength \@ydim=\@YPuno\unitlength + \pIIe@bezier@QtoC\@ovxx\@ovdx\@ovro + \pIIe@bezier@QtoC\@ovyy\@ovdy\@ovri + \pIIe@bezier@QtoC\@xdim\@ovdx\@clnwd + \pIIe@bezier@QtoC\@ydim\@ovdy\@clnht +% \end{macrocode} +% +% We call the basic |pict2e| macro to draw a cubic spline and we finish +% the conditional statements with which we started these calculations; +% eventually we close the group we opened at the beginning and we copy +% the terminal node information (position and direction) into the +% 0-labelled macros that indicate the starting point of the next arc. +% \begin{macrocode} + \pIIe@curveto\@ovro\@ovri\@clnwd\@clnht\@xdim\@ydim +\fi\fi\egroup +\CopyVect\@Puno to\@Pzero +\CopyVect\@Duno to\@Dzero +\ignorespaces} +% \end{macrocode} +% +% An example of usage is shown at the left in +% figure~\ref{fig:quadratic-arcs}\footnote{The commands \cs{legenda}, +% \cs{Pall} and \cs{Zbox} are specifically defined in the preamble of this +% document; they must be used within a \texttt{picture} environment. +% \cs{legenda} draws a framed legend made up of a single (short) math +% formula; \cs{Pall} is just a shorthand to put a filled small circle at a +% specified position' \cs{Zbox} puts a symbol in math mode a little +% displaced in the proper direction relative to a specified position. +% They are just handy to label certain objects in a \texttt{picture} +% diagram, but they are not part of the \texttt{curve2e} package.}. +% created with the code shown within figure~\ref{fig:quadratic-arcs}. +% +% Notice also that the inflexed line is made with two arcs that meet at +% the inflection point; the same is true for the line that resembles +% a sine wave. The cusps of the inner border of the green area are +% obtained with the usual optional argument already used also with the +% |\Curve| recursive macro. +% +% The ``circle'' inside the square frame is visibly different from a real +% circle, in spite of the fact that the maximum deviation from the true +% circle is just about 6\% relative to the radius; a quarter circle +% obtained with a single parabola is definitely a poor approximation of a +% real quarter circle; possibly by splitting each quarter circle in three +% or four partial arcs the approximation of a real quarter circle would be +% much better. On the right of figure~\ref{fig:quadratic-arcs} it is +% possible to compare a “circle” obtained with quadratic arcs with the the +% internal circle obtained with cubic arcs; the difference is easily seen +% even without using measuring instruments. +% +% With quadratic arcs we decided to avoid defining specific macros similar +% to |\CurveBetween| and |\CbezierBetween|; the first macro would not save +% any typing to the operator; furthermore it may be questionable if it was +% really useful even with cubic splines; the second macro with quadratic +% arcs is meaningless, since with quadratic arcs there is just one control +% point and there is no choice on its position. +% +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \section{Conclusion} +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% I believe that the set of new macros provided by this package can really +% help the user to draw his/her diagrams with more agility; it will be the +% accumulated experience to decide if this is true. +% +% As a personal experience we found very comfortable to draw ellipses and +% to define macros to draw not only such shapes or filled elliptical +% areas, but also to create “legends” with coloured backgrounds and +% borders. But this is an application of the functionality implemented in +% this package. +% +%\iffalse +% +%\fi +% +% +%\iffalse +%<*readme> +%\fi +% \section{The \texttt{README.txt} file} +%The following it the text that forms the contents of the |README.txt| +% file that accompanies the package. We fount it handy to have it in +% the documented source, because in this way certain informations +% don't need to be repeated again and again in different files. +% \begin{macrocode} +The package bundle curve2e is composed of the following files + +curve2e.dtx +curve2e.pdf +README.txt +curve2e-v161.sty +ltxdoc.cfg + +curve2e.dtx is the documented TeX source file of file curve2e.sty; you get +both curve2e.sty and curve2e.pdf by running pdflatex on curve2e.dtx. +The ltxdoc.cfg file customises the way the documentation file is typeset. +This .cfg file is not subject to the LPPL licence. + +README.txt, this file, contains general information. + +Curve2e-v161.sty contains the previous version of the package; see below +why the older version might become necessary for the end user. + +Curve2e.sty is an extension of the package pict2e.sty which extends the +standard picture LaTeX environment according to what Leslie Lamport +specified in the second edition of his LaTeX manual. + +This further extension allows to draw lines and vectors with any non +integer slope parameters, to draw dashed lined of any slope, to draw arcs +and curved vectors, to draw curves where just the interpolating nodes are +specified together with the slopes at the nodes; closed paths of any shape +can be filled with color; all coordinates are treated as ordered pairs, +i.e. 'complex numbers'; coordinates may be expressed also in polar form. +Some of these features have been incorporated in the 2011 version of +pict2e; therefore this package avoids any modification to the original +pict2e commands. + + +Curve2e now accepts polar coordinates in addition to the usual cartesian +ones; several macros have been upgraded and a new macro for tracing cubic +Bezier splines with their control nodes specified in polar form is available. The same applies to quadratic Bezier splines. + +This version solves a conflict with package eso-pic. + +This version of curve2e is almost fully compatible with pict2e dated +2014/01/12 version 0.2z. + +If you specify + +\usepackage[]{curve2e} + +the package pict2e is automatically invoked with the specified options. + +The -almost compatible- frase is necessary to explain that this version +of curve2e uses some `functions' of the LaTeX3 language that were made +available to the LaTeX developer by mid October 2018. Should the user +have an older or a basic/incomplete installation of the TeX system, +such L3 functions might not be available. This is why this +package checks the presence of the developer interface; in case +such interface is not available it falls back to the previous version +renamed curve2e-v161.sty, which is part of this bundle, and that must +not be renamed in any way. The compatibility mentioned above implies +that the user macros remain the same, but their implementation requires +the L3 interface. + +The package has the LPPL status of author maintained. + +According to the LPPL licence, you are entitled to modify this package, +as long as you fulfil the few conditions set forth by the Licence. + +Nevertheless this package is an extension to the standard LaTeX package +pict2e (2014). Therefore any change must be controlled on the +parent package pict2e, so as to avoid redefining what has already been +incorporated in the official package. + +If you prefer sending me your modifications, as long as I will maintain +this package, I will possibly include every (documented) suggestion or +modification into this package and, of course, I will acknowledge your +contribution. + +Claudio Beccari + +claudio dot beccari at gmail dot com +% \end{macrocode} +%\iffalse +% +%\fi +%\iffalse +%<*v161> +%\fi +% \section{The fall-back package version \texttt{curve2e-v161}} +% this is the fall-back version of |curve2e-v161.sty| to which the main +% file |curve2e.sty| falls back in case the interface package |xfp| is not +% available. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e}[2016/01/01] +\ProvidesPackage{curve2e-v161}% + [2019/02/07 v.1.61 Extension package for pict2e] + +\RequirePackage{color} +\RequirePackageWithOptions{pict2e}[2014/01/01] +\RequirePackage{xparse} +\def\TRON{\tracingcommands\tw@ \tracingmacros\tw@}% +\def\TROF{\tracingcommands\z@ \tracingmacros\z@}% +\ifx\undefined\@tdA \newdimen\@tdA \fi +\ifx\undefined\@tdB \newdimen\@tdB \fi +\ifx\undefined\@tdC \newdimen\@tdC \fi +\ifx\undefined\@tdD \newdimen\@tdD \fi +\ifx\undefined\@tdE \newdimen\@tdE \fi +\ifx\undefined\@tdF \newdimen\@tdF \fi +\ifx\undefined\defaultlinewidth \newdimen\defaultlinewidth \fi +\gdef\linethickness#1{\@wholewidth#1\@halfwidth.5\@wholewidth\ignorespaces}% +\newcommand\defaultlinethickness[1]{\defaultlinewidth=#1\relax +\def\thicklines{\linethickness{\defaultlinewidth}}% +\def\thinlines{\linethickness{.5\defaultlinewidth}}% +\thinlines\ignorespaces} +\def\LIne(#1){{\GetCoord(#1)\@tX\@tY + \moveto(0,0) + \pIIe@lineto{\@tX\unitlength}{\@tY\unitlength}\strokepath}\ignorespaces}% +\def\segment(#1)(#2){\@killglue\polyline(#1)(#2)}% +\def\line(#1)#2{\begingroup + \@linelen #2\unitlength + \ifdim\@linelen<\z@\@badlinearg\else + \expandafter\DirOfVect#1to\Dir@line + \GetCoord(\Dir@line)\d@mX\d@mY + \ifdim\d@mX\p@=\z@\else + \DividE\ifdim\d@mX\p@<\z@-\fi\p@ by\d@mX\p@ to\sc@lelen + \@linelen=\sc@lelen\@linelen + \fi + \moveto(0,0) + \pIIe@lineto{\d@mX\@linelen}{\d@mY\@linelen}% + \strokepath + \fi +\endgroup\ignorespaces}% +\ifx\Dashline\undefined +\def\Dashline{\@ifstar{\Dashline@@}{\Dashline@}} +\def\Dashline@(#1)(#2)#3{% +\bgroup + \countdef\NumA3254\countdef\NumB3252\relax + \GetCoord(#1)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttA + \GetCoord(#2)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttB + \SubVect\V@ttA from\V@ttB to\V@ttC + \ModOfVect\V@ttC to\DlineMod + \DivideFN\DlineMod by#3 to\NumD + \NumA\expandafter\Integer\NumD.?? + \ifodd\NumA\else\advance\NumA\@ne\fi + \NumB=\NumA \divide\NumB\tw@ + \DividE\DlineMod\p@ by\NumA\p@ to\D@shMod + \DividE\p@ by\NumA\p@ to \@tempa + \MultVect\V@ttC by\@tempa,0 to\V@ttB + \MultVect\V@ttB by 2,0 to\V@ttC + \advance\NumB\@ne + \edef\@mpt{\noexpand\egroup + \noexpand\multiput(\V@ttA)(\V@ttC){\number\NumB}% + {\noexpand\LIne(\V@ttB)}}% + \@mpt\ignorespaces}% +\let\Dline\Dashline + +\def\Dashline@@(#1)(#2)#3{\put(#1){\Dashline@(0,0)(#2){#3}}} +\fi +\ifx\Dotline\undefined +\def\Dotline{\@ifstar{\Dotline@@}{\Dotline@}} +\def\Dotline@(#1)(#2)#3{% +\bgroup + \countdef\NumA 3254\relax \countdef\NumB 3255\relax + \GetCoord(#1)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttA + \GetCoord(#2)\@tA\@tB \MakeVectorFrom\@tA\@tB to\V@ttB + \SubVect\V@ttA from\V@ttB to\V@ttC + \ModOfVect\V@ttC to\DotlineMod + \DivideFN\DotlineMod by#3 to\NumD + \NumA=\expandafter\Integer\NumD.?? + \DivVect\V@ttC by\NumA,0 to\V@ttB + \advance\NumA\@ne + \edef\@mpt{\noexpand\egroup + \noexpand\multiput(\V@ttA)(\V@ttB){\number\NumA}% + {\noexpand\makebox(0,0){\noexpand\circle*{0.5}}}}% + \@mpt\ignorespaces}% + +\def\Dotline@@(#1)(#2)#3{\put(#1){\Dotline@(0,0)(#2){#3}}} +\fi +\AtBeginDocument{\@ifpackageloaded{eso-pic}{% +\renewcommand\LenToUnit[1]{\strip@pt\dimexpr#1*\p@/\unitlength}}{}} + +\def\GetCoord(#1)#2#3{% +\expandafter\SplitNod@\expandafter(#1)#2#3\ignorespaces} +\def\isnot@polar#1:#2!!{\def\@tempOne{#2}\ifx\@tempOne\empty +\expandafter\@firstoftwo\else +\expandafter\@secondoftwo\fi +{\SplitNod@@}{\SplitPolar@@}} + +\def\SplitNod@(#1)#2#3{\isnot@polar#1:!!(#1)#2#3}% +\def\SplitNod@@(#1,#2)#3#4{\edef#3{#1}\edef#4{#2}}% +\def\SplitPolar@@(#1:#2)#3#4{\DirFromAngle#1to\@DirA +\ScaleVect\@DirA by#2to\@DirA +\expandafter\SplitNod@@\expandafter(\@DirA)#3#4} + +\let\originalput\put +\def\put(#1){\bgroup\GetCoord(#1)\@tX\@tY +\edef\x{\noexpand\egroup\noexpand\originalput(\@tX,\@tY)}\x} + +\let\originalmultiput\multiput +\let\original@multiput\@multiput + +\long\def\@multiput(#1)#2#3{\bgroup\GetCoord(#1)\@mptX\@mptY +\edef\x{\noexpand\egroup\noexpand\original@multiput(\@mptX,\@mptY)}% +\x{#2}{#3}\ignorespaces} + +\gdef\multiput(#1)#2{\bgroup\GetCoord(#1)\@mptX\@mptY +\edef\x{\noexpand\egroup\noexpand\originalmultiput(\@mptX,\@mptY)}\x(}%) + \def\vector(#1)#2{% + \begingroup + \GetCoord(#1)\d@mX\d@mY + \@linelen#2\unitlength + \ifdim\d@mX\p@=\z@\ifdim\d@mY\p@=\z@\@badlinearg\fi\fi + \ifdim\@linelen<\z@ \@linelen=-\@linelen\fi + \MakeVectorFrom\d@mX\d@mY to\@Vect + \DirOfVect\@Vect to\Dir@Vect + \YpartOfVect\Dir@Vect to\@ynum \@ydim=\@ynum\p@ + \XpartOfVect\Dir@Vect to\@xnum \@xdim=\@xnum\p@ + \ifdim\d@mX\p@=\z@ + \else\ifdim\d@mY\p@=\z@ + \else + \DividE\ifdim\@xnum\p@<\z@-\fi\p@ by\@xnum\p@ to\sc@lelen + \@linelen=\sc@lelen\@linelen + \fi + \fi + \@tdB=\@linelen +\pIIe@concat\@xdim\@ydim{-\@ydim}\@xdim{\@xnum\@linelen}{\@ynum\@linelen}% + \@linelen\z@ + \pIIe@vector + \fillpath + \@linelen=\@tdB + \@tdA=\pIIe@FAW\@wholewidth + \@tdA=\pIIe@FAL\@tdA + \advance\@linelen-\@tdA + \ifdim\@linelen>\z@ + \moveto(0,0) + \pIIe@lineto{\@xnum\@linelen}{\@ynum\@linelen}% + \strokepath\fi + \endgroup} +\def\Vector(#1){{% +\GetCoord(#1)\@tX\@tY +\ifdim\@tX\p@=\z@\vector(\@tX,\@tY){\@tY} +\else +\vector(\@tX,\@tY){\@tX}\fi}} +\def\VECTOR(#1)(#2){\begingroup +\SubVect#1from#2to\@tempa +\expandafter\put\expandafter(#1){\expandafter\Vector\expandafter(\@tempa)}% +\endgroup\ignorespaces} +\let\lp@r( \let\rp@r) +\renewcommand*\polyline[1][\beveljoin]{\p@lylin@[#1]} + +\def\p@lylin@[#1](#2){\@killglue#1\GetCoord(#2)\d@mX\d@mY + \pIIe@moveto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\p@lyline}{% + \PackageWarning{curve2e}% + {Polylines require at least two vertices!\MessageBreak + Control your polyline specification\MessageBreak}% + \ignorespaces}} + +\def\p@lyline(#1){\GetCoord(#1)\d@mX\d@mY + \pIIe@lineto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\p@lyline}{\strokepath\ignorespaces}} +\providecommand\polygon{} +\RenewDocumentCommand\polygon{s O{\beveljoin} }{\@killglue\begingroup +\IfBooleanTF{#1}{\@tempswatrue}{\@tempswafalse}% +\@polygon[#2]} + +\def\@polygon[#1](#2){\@killglue#1\GetCoord(#2)\d@mX\d@mY + \pIIe@moveto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\@@polygon}{% + \PackageWarning{curve2e}% + {Polygons require at least two vertices!\MessageBreak + Control your polygon specification\MessageBreak}% + \ignorespaces}} + + \def\@@polygon(#1){\GetCoord(#1)\d@mX\d@mY + \pIIe@lineto{\d@mX\unitlength}{\d@mY\unitlength}% + \@ifnextchar\lp@r{\@@polygon}{\pIIe@closepath + \if@tempswa\pIIe@fillGraph\else\pIIe@strokeGraph\fi + \endgroup + \ignorespaces}} +\def\GraphGrid(#1,#2){\bgroup\textcolor{red}{\linethickness{.1\p@}% +\RoundUp#1modulo10to\@GridWd \RoundUp#2modulo10to\@GridHt +\@tempcnta=\@GridWd \divide\@tempcnta10\relax \advance\@tempcnta\@ne +\multiput(0,0)(10,0){\@tempcnta}{\line(0,1){\@GridHt}}% +\@tempcnta=\@GridHt \divide\@tempcnta10\advance\@tempcnta\@ne +\multiput(0,0)(0,10){\@tempcnta}{\line(1,0){\@GridWd}}\thinlines}% +\egroup\ignorespaces} +\def\RoundUp#1modulo#2to#3{\expandafter\@tempcnta\Integer#1.??% +\count254\@tempcnta\divide\count254by#2\relax +\multiply\count254by#2\relax +\count252\@tempcnta\advance\count252-\count254 +\ifnum\count252>0\advance\count252-#2\relax +\advance\@tempcnta-\count252\fi\edef#3{\number\@tempcnta}\ignorespaces}% +\def\Integer#1.#2??{#1}% +\ifdefined\dimexpr + \unless\ifdefined\DividE +\def\DividE#1by#2to#3{\bgroup +\dimendef\Num2254\relax \dimendef\Den2252\relax +\dimendef\@DimA 2250 +\Num=\p@ \Den=#2\relax +\ifdim\Den=\z@ + \edef\x{\noexpand\endgroup\noexpand\def\noexpand#3{\strip@pt\maxdimen}}% +\else + \@DimA=#1\relax + \edef\x{% + \noexpand\egroup\noexpand\def\noexpand#3{% + \strip@pt\dimexpr\@DimA*\Num/\Den\relax}}% +\fi +\x\ignorespaces}% +\fi + \unless\ifdefined\DivideFN + \def\DivideFN#1by#2to#3{\DividE#1\p@ by#2\p@ to{#3}}% + \fi + \unless\ifdefined\MultiplY + \def\MultiplY#1by#2to#3{\bgroup + \dimendef\@DimA 2254 \dimendef\@DimB2255 + \@DimA=#1\p@\relax \@DimB=#2\p@\relax + \edef\x{% + \noexpand\egroup\noexpand\def\noexpand#3{% + \strip@pt\dimexpr\@DimA*\@DimB/\p@\relax}}% + \x\ignorespaces}% + \let\MultiplyFN\MultiplY + \fi +\fi + +\unless\ifdefined\Numero + \def\Numero#1#2{\bgroup\dimen3254=#2\relax + \edef\x{\noexpand\egroup\noexpand\edef\noexpand#1{% + \strip@pt\dimen3254}}\x\ignorespaces}% +\fi +\def\g@tTanCotanFrom#1to#2and#3{% +\DividE 114.591559\p@ by#1to\X@ \@tdB=\X@\p@ +\countdef\I=2546\def\Tan{0}\I=11\relax +\@whilenum\I>\z@\do{% + \@tdC=\Tan\p@ \@tdD=\I\@tdB + \advance\@tdD-\@tdC \DividE\p@ by\@tdD to\Tan + \advance\I-2\relax}% +\def#2{\Tan}\DividE\p@ by\Tan\p@ to\Cot \def#3{\Cot}\ignorespaces}% +\def\SinOf#1to#2{\bgroup% +\@tdA=#1\p@% +\ifdim\@tdA>\z@% + \@whiledim\@tdA>180\p@\do{\advance\@tdA -360\p@}% +\else% + \@whiledim\@tdA<-180\p@\do{\advance\@tdA 360\p@}% +\fi \ifdim\@tdA=\z@ + \def\@tempA{0}% +\else + \ifdim\@tdA>\z@ + \def\Segno{+}% + \else + \def\Segno{-}% + \@tdA=-\@tdA + \fi + \ifdim\@tdA>90\p@ + \@tdA=-\@tdA \advance\@tdA 180\p@ + \fi + \ifdim\@tdA=90\p@ + \def\@tempA{\Segno1}% + \else + \ifdim\@tdA=180\p@ + \def\@tempA{0}% + \else + \ifdim\@tdA<\p@ + \@tdA=\Segno0.0174533\@tdA + \DividE\@tdA by\p@ to \@tempA% + \else + \g@tTanCotanFrom\@tdA to\T and\Tp + \@tdA=\T\p@ \advance\@tdA \Tp\p@ + \DividE \Segno2\p@ by\@tdA to \@tempA% + \fi + \fi + \fi +\fi +\edef\endSinOf{\noexpand\egroup + \noexpand\def\noexpand#2{\@tempA}\noexpand\ignorespaces}% +\endSinOf}% +\def\CosOf#1to#2{\bgroup% +\@tdA=#1\p@% +\ifdim\@tdA>\z@% + \@whiledim\@tdA>360\p@\do{\advance\@tdA -360\p@}% +\else% + \@whiledim\@tdA<\z@\do{\advance\@tdA 360\p@}% +\fi +\ifdim\@tdA>180\p@ + \@tdA=-\@tdA \advance\@tdA 360\p@ +\fi +\ifdim\@tdA<90\p@ + \def\Segno{+}% +\else + \def\Segno{-}% + \@tdA=-\@tdA \advance\@tdA 180\p@ +\fi +\ifdim\@tdA=\z@ + \def\@tempA{\Segno1}% +\else + \ifdim\@tdA<\p@ + \@tdA=0.0174533\@tdA \Numero\@tempA\@tdA + \@tdA=\@tempA\@tdA \@tdA=-.5\@tdA + \advance\@tdA \p@ + \DividE\@tdA by\p@ to\@tempA% + \else + \ifdim\@tdA=90\p@ + \def\@tempA{0}% + \else + \g@tTanCotanFrom\@tdA to\T and\Tp + \@tdA=\Tp\p@ \advance\@tdA-\T\p@ + \@tdB=\Tp\p@ \advance\@tdB\T\p@ + \DividE\Segno\@tdA by\@tdB to\@tempA% + \fi + \fi +\fi +\edef\endCosOf{\noexpand\egroup + \noexpand\def\noexpand#2{\@tempA}\noexpand\ignorespaces}% +\endCosOf}% +\def\TanOf#1to#2{\bgroup% +\@tdA=#1\p@% +\ifdim\@tdA>90\p@% + \@whiledim\@tdA>90\p@\do{\advance\@tdA -180\p@}% +\else% + \@whiledim\@tdA<-90\p@\do{\advance\@tdA 180\p@}% +\fi% +\ifdim\@tdA=\z@% + \def\@tempA{0}% +\else + \ifdim\@tdA>\z@ + \def\Segno{+}% + \else + \def\Segno{-}% + \@tdA=-\@tdA + \fi + \ifdim\@tdA=90\p@ + \def\@tempA{\Segno16383.99999}% + \else + \ifdim\@tdA<\p@ + \@tdA=\Segno0.0174533\@tdA + \DividE\@tdA by\p@ to\@tempA% + \else + \g@tTanCotanFrom\@tdA to\T and\Tp + \@tdA\Tp\p@ \advance\@tdA -\T\p@ + \DividE\Segno2\p@ by\@tdA to\@tempA% + \fi + \fi +\fi +\edef\endTanOf{\noexpand\egroup + \noexpand\def\noexpand#2{\@tempA}\noexpand\ignorespaces}% +\endTanOf}% +\def\ArcTanOf#1to#2{\bgroup +\countdef\Inverti 4444\Inverti=0 +\def\Segno{} +\edef\@tF{#1}\@tdF=\@tF\p@ \@tdE=57.295778\p@ +\@tdD=\ifdim\@tdF<\z@ -\@tdF\def\Segno{-}\else\@tdF\fi +\ifdim\@tdD>\p@ +\Inverti=\@ne +\@tdD=\dimexpr\p@*\p@/\@tdD\relax +\fi +\unless\ifdim\@tdD>0.02\p@ + \def\@tX{\strip@pt\dimexpr57.295778\@tdD\relax}% +\else + \edef\@tX{45}\relax + \countdef\I 2523 \I=9\relax + \@whilenum\I>0\do{\TanOf\@tX to\@tG + \edef\@tG{\strip@pt\dimexpr\@tG\p@-\@tdD\relax}\relax + \MultiplY\@tG by57.295778to\@tG + \CosOf\@tX to\@tH + \MultiplY\@tH by\@tH to\@tH + \MultiplY\@tH by\@tG to \@tH + \edef\@tX{\strip@pt\dimexpr\@tX\p@ - \@tH\p@\relax}\relax + \advance\I\m@ne}% +\fi +\ifnum\Inverti=\@ne +\edef\@tX{\strip@pt\dimexpr90\p@-\@tX\p@\relax} +\fi +\edef\x{\egroup\noexpand\edef\noexpand#2{\Segno\@tX}}\x\ignorespaces}% +\def\MakeVectorFrom#1#2to#3{\edef#3{#1,#2}\ignorespaces}% +\def\CopyVect#1to#2{\edef#2{#1}\ignorespaces}% +\def\ModOfVect#1to#2{\GetCoord(#1)\t@X\t@Y +\@tempdima=\t@X\p@ \ifdim\@tempdima<\z@ \@tempdima=-\@tempdima\fi +\@tempdimb=\t@Y\p@ \ifdim\@tempdimb<\z@ \@tempdimb=-\@tempdimb\fi +\ifdim\@tempdima=\z@ + \ifdim\@tempdimb=\z@ + \def\@T{0}\@tempdimc=\z@ + \else + \def\@T{0}\@tempdimc=\@tempdimb + \fi +\else + \ifdim\@tempdima>\@tempdimb + \DividE\@tempdimb by\@tempdima to\@T + \@tempdimc=\@tempdima + \else + \DividE\@tempdima by\@tempdimb to\@T + \@tempdimc=\@tempdimb + \fi +\fi +\unless\ifdim\@tempdimc=\z@ + \unless\ifdim\@T\p@=\z@ + \@tempdima=\@T\p@ \@tempdima=\@T\@tempdima + \advance\@tempdima\p@% + \@tempdimb=\p@% + \@tempcnta=5\relax + \@whilenum\@tempcnta>\z@\do{\DividE\@tempdima by\@tempdimb to\@T + \advance\@tempdimb \@T\p@ \@tempdimb=.5\@tempdimb + \advance\@tempcnta\m@ne}% + \@tempdimc=\@T\@tempdimc + \fi +\fi +\Numero#2\@tempdimc +\ignorespaces}% +\def\DirOfVect#1to#2{\GetCoord(#1)\t@X\t@Y +\ModOfVect#1to\@tempa +\unless\ifdim\@tempdimc=\z@ + \DividE\t@X\p@ by\@tempdimc to\t@X + \DividE\t@Y\p@ by\@tempdimc to\t@Y +\fi +\MakeVectorFrom\t@X\t@Y to#2\ignorespaces}% +\def\ModAndDirOfVect#1to#2and#3{% +\GetCoord(#1)\t@X\t@Y +\ModOfVect#1to#2% +\ifdim\@tempdimc=\z@\else + \DividE\t@X\p@ by\@tempdimc to\t@X + \DividE\t@Y\p@ by\@tempdimc to\t@Y +\fi +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +\def\DistanceAndDirOfVect#1minus#2to#3and#4{% +\SubVect#2from#1to\@tempa +\ModAndDirOfVect\@tempa to#3and#4\ignorespaces}% +\def\XpartOfVect#1to#2{% +\GetCoord(#1)#2\@tempa\ignorespaces}% +\def\YpartOfVect#1to#2{% +\GetCoord(#1)\@tempa#2\ignorespaces}% +\def\DirFromAngle#1to#2{% +\CosOf#1to\t@X +\SinOf#1to\t@Y +\MakeVectorFrom\t@X\t@Y to#2\ignorespaces}% +\def\ArgOfVect#1to#2{\bgroup\GetCoord(#1){\t@X}{\t@Y}% +\def\s@gno{}\def\addflatt@ngle{0} +\ifdim\t@X\p@=\z@ + \ifdim\t@Y\p@=\z@ + \def\ArcTan{0}% + \else + \def\ArcTan{90}% + \ifdim\t@Y\p@<\z@\def\s@gno{-}\fi + \fi +\else + \ifdim\t@Y\p@=\z@ + \ifdim\t@X\p@<\z@ + \def\ArcTan{180}% + \else + \def\ArcTan{0}% + \fi + \else + \ifdim\t@X\p@<\z@% + \def\addflatt@ngle{180}% + \edef\t@X{\strip@pt\dimexpr-\t@X\p@}% + \edef\t@Y{\strip@pt\dimexpr-\t@Y\p@}% + \ifdim\t@Y\p@<\z@ + \def\s@gno{-}% + \edef\t@Y{-\t@Y}% + \fi + \fi + \DivideFN\t@Y by\t@X to \t@A + \ArcTanOf\t@A to\ArcTan + \fi +\fi +\edef\ArcTan{\unless\ifx\s@gno\empty\s@gno\fi\ArcTan}% +\unless\ifnum\addflatt@ngle=0\relax + \edef\ArcTan{% + \strip@pt\dimexpr\ArcTan\p@\ifx\s@gno\empty-\else+\fi + \addflatt@ngle\p@\relax}% +\fi +\edef\x{\noexpand\egroup\noexpand\edef\noexpand#2{\ArcTan}}% +\x\ignorespaces} +\def\ScaleVect#1by#2to#3{\GetCoord(#1)\t@X\t@Y +\@tempdima=\t@X\p@ \@tempdima=#2\@tempdima\Numero\t@X\@tempdima +\@tempdima=\t@Y\p@ \@tempdima=#2\@tempdima\Numero\t@Y\@tempdima +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +\def\ConjVect#1to#2{\GetCoord(#1)\t@X\t@Y +\@tempdima=-\t@Y\p@\Numero\t@Y\@tempdima +\MakeVectorFrom\t@X\t@Y to#2\ignorespaces}% +\def\AddVect#1and#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\@tempdima\tu@X\p@\advance\@tempdima\td@X\p@ \Numero\t@X\@tempdima +\@tempdima\tu@Y\p@\advance\@tempdima\td@Y\p@ \Numero\t@Y\@tempdima +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +\def\SubVect#1from#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\@tempdima\td@X\p@\advance\@tempdima-\tu@X\p@ \Numero\t@X\@tempdima +\@tempdima\td@Y\p@\advance\@tempdima-\tu@Y\p@ \Numero\t@Y\@tempdima +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +\def\MultVect#1by{\@ifstar{\@ConjMultVect#1by}{\@MultVect#1by}}% +\def\@MultVect#1by#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y +\@tempdima\tu@X\p@ \@tempdimb\tu@Y\p@ +\@tempdimc=\td@X\@tempdima\advance\@tempdimc-\td@Y\@tempdimb +\Numero\t@X\@tempdimc +\@tempdimc=\td@Y\@tempdima\advance\@tempdimc\td@X\@tempdimb +\Numero\t@Y\@tempdimc +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces}% +\def\@ConjMultVect#1by#2to#3{\GetCoord(#1)\tu@X\tu@Y +\GetCoord(#2)\td@X\td@Y \@tempdima\tu@X\p@ \@tempdimb\tu@Y\p@ +\@tempdimc=\td@X\@tempdima\advance\@tempdimc+\td@Y\@tempdimb +\Numero\t@X\@tempdimc +\@tempdimc=\td@X\@tempdimb\advance\@tempdimc-\td@Y\@tempdima +\Numero\t@Y\@tempdimc +\MakeVectorFrom\t@X\t@Y to#3\ignorespaces} +\def\DivVect#1by#2to#3{\ModAndDirOfVect#2to\@Mod and\@Dir +\DividE\p@ by\@Mod\p@ to\@Mod \ConjVect\@Dir to\@Dir +\ScaleVect#1by\@Mod to\@tempa +\MultVect\@tempa by\@Dir to#3\ignorespaces}% +\def\Arc(#1)(#2)#3{\begingroup +\@tdA=#3\p@ +\unless\ifdim\@tdA=\z@ + \@Arc(#1)(#2)% +\fi +\endgroup\ignorespaces}% +\def\@Arc(#1)(#2){% +\ifdim\@tdA>\z@ + \let\Segno+% +\else + \@tdA=-\@tdA \let\Segno-% +\fi +\Numero\@gradi\@tdA +\ifdim\@tdA>360\p@ + \PackageWarning{curve2e}{The arc aperture is \@gradi\space degrees + and gets reduced\MessageBreak% + to the range 0--360 taking the sign into consideration}% + \@whiledim\@tdA>360\p@\do{\advance\@tdA-360\p@}% +\fi +\SubVect#2from#1to\@V \ModOfVect\@V to\@Raggio \CopyVect#2to\@pPun +\CopyVect#1to\@Cent \GetCoord(\@pPun)\@pPunX\@pPunY +\@@Arc +\strokepath\ignorespaces}% +\def\@@Arc{% +\pIIe@moveto{\@pPunX\unitlength}{\@pPunY\unitlength}% +\ifdim\@tdA>180\p@ + \advance\@tdA-180\p@ + \Numero\@gradi\@tdA + \SubVect\@pPun from\@Cent to\@V + \AddVect\@V and\@Cent to\@sPun + \MultVect\@V by0,-1.3333333to\@V \if\Segno-\ScaleVect\@V by-1to\@V\fi + \AddVect\@pPun and\@V to\@pcPun + \AddVect\@sPun and\@V to\@scPun + \GetCoord(\@pcPun)\@pcPunX\@pcPunY + \GetCoord(\@scPun)\@scPunX\@scPunY + \GetCoord(\@sPun)\@sPunX\@sPunY + \pIIe@curveto{\@pcPunX\unitlength}{\@pcPunY\unitlength}% + {\@scPunX\unitlength}{\@scPunY\unitlength}% + {\@sPunX\unitlength}{\@sPunY\unitlength}% + \CopyVect\@sPun to\@pPun +\fi +\ifdim\@tdA>\z@ + \DirFromAngle\@gradi to\@Dir \if\Segno-\ConjVect\@Dir to\@Dir \fi + \SubVect\@Cent from\@pPun to\@V + \MultVect\@V by\@Dir to\@V + \AddVect\@Cent and\@V to\@sPun + \@tdA=.5\@tdA \Numero\@gradi\@tdA + \DirFromAngle\@gradi to\@Phimezzi + \GetCoord(\@Phimezzi)\@cosphimezzi\@sinphimezzi + \@tdB=1.3333333\p@ \@tdB=\@Raggio\@tdB + \@tdC=\p@ \advance\@tdC -\@cosphimezzi\p@ \Numero\@tempa\@tdC + \@tdB=\@tempa\@tdB + \DividE\@tdB by\@sinphimezzi\p@ to\@cZ + \ScaleVect\@Phimezzi by\@cZ to\@Phimezzi + \ConjVect\@Phimezzi to\@mPhimezzi + \if\Segno-% + \let\@tempa\@Phimezzi + \let\@Phimezzi\@mPhimezzi + \let\@mPhimezzi\@tempa + \fi + \SubVect\@sPun from\@pPun to\@V + \DirOfVect\@V to\@V + \MultVect\@Phimezzi by\@V to\@Phimezzi + \AddVect\@sPun and\@Phimezzi to\@scPun + \ScaleVect\@V by-1to\@V + \MultVect\@mPhimezzi by\@V to\@mPhimezzi + \AddVect\@pPun and\@mPhimezzi to\@pcPun + \GetCoord(\@pcPun)\@pcPunX\@pcPunY + \GetCoord(\@scPun)\@scPunX\@scPunY + \GetCoord(\@sPun)\@sPunX\@sPunY + \pIIe@curveto{\@pcPunX\unitlength}{\@pcPunY\unitlength}% + {\@scPunX\unitlength}{\@scPunY\unitlength}% + {\@sPunX\unitlength}{\@sPunY\unitlength}% +\fi} +\def\VectorArc(#1)(#2)#3{\begingroup +\@tdA=#3\p@ \ifdim\@tdA=\z@\else + \@VArc(#1)(#2)% +\fi +\endgroup\ignorespaces}% +\def\VectorARC(#1)(#2)#3{\begingroup +\@tdA=#3\p@ +\ifdim\@tdA=\z@\else + \@VARC(#1)(#2)% +\fi +\endgroup\ignorespaces}% +\def\@VArc(#1)(#2){% +\ifdim\@tdA>\z@ + \let\Segno+% +\else + \@tdA=-\@tdA \let\Segno-% +\fi \Numero\@gradi\@tdA +\ifdim\@tdA>360\p@ + \PackageWarning{curve2e}{The arc aperture is \@gradi\space degrees + and gets reduced\MessageBreak% + to the range 0--360 taking the sign into consideration}% + \@whiledim\@tdA>360\p@\do{\advance\@tdA-360\p@}% +\fi +\SubVect#1from#2to\@V \ModOfVect\@V to\@Raggio \CopyVect#2to\@pPun +\@tdE=\pIIe@FAW\@wholewidth \@tdE=\pIIe@FAL\@tdE +\DividE\@tdE by \@Raggio\unitlength to\DeltaGradi +\@tdD=\DeltaGradi\p@ +\@tdD=57.29578\@tdD \Numero\DeltaGradi\@tdD +\@tdD=\ifx\Segno--\fi\@gradi\p@ \Numero\@tempa\@tdD +\DirFromAngle\@tempa to\@Dir +\MultVect\@V by\@Dir to\@sPun +\edef\@tempA{\ifx\Segno-\m@ne\else\@ne\fi}% +\MultVect\@sPun by 0,\@tempA to\@vPun +\DirOfVect\@vPun to\@Dir +\AddVect\@sPun and #1 to \@sPun +\GetCoord(\@sPun)\@tdX\@tdY +\@tdD\ifx\Segno--\fi\DeltaGradi\p@ +\@tdD=.5\@tdD \Numero\DeltaGradi\@tdD +\DirFromAngle\DeltaGradi to\@Dird +\MultVect\@Dir by*\@Dird to\@Dir +\GetCoord(\@Dir)\@xnum\@ynum +\put(\@tdX,\@tdY){\vector(\@xnum,\@ynum){0}}% +\@tdE =\ifx\Segno--\fi\DeltaGradi\p@ +\advance\@tdA -\@tdE \Numero\@gradi\@tdA +\CopyVect#1to\@Cent \GetCoord(\@pPun)\@pPunX\@pPunY +\@@Arc +\strokepath\ignorespaces}% +\def\@VARC(#1)(#2){% +\ifdim\@tdA>\z@ + \let\Segno+% +\else + \@tdA=-\@tdA \let\Segno-% +\fi \Numero\@gradi\@tdA +\ifdim\@tdA>360\p@ + \PackageWarning{curve2e}{The arc aperture is \@gradi\space degrees + and gets reduced\MessageBreak% + to the range 0--360 taking the sign into consideration}% + \@whiledim\@tdA>360\p@\do{\advance\@tdA-360\p@}% +\fi +\SubVect#1from#2to\@V \ModOfVect\@V to\@Raggio \CopyVect#2to\@pPun +\@tdE=\pIIe@FAW\@wholewidth \@tdE=0.8\@tdE +\DividE\@tdE by \@Raggio\unitlength to\DeltaGradi +\@tdD=\DeltaGradi\p@ \@tdD=57.29578\@tdD \Numero\DeltaGradi\@tdD +\@tdD=\if\Segno--\fi\@gradi\p@ \Numero\@tempa\@tdD +\DirFromAngle\@tempa to\@Dir +\MultVect\@V by\@Dir to\@sPun% corrects the end point +\edef\@tempA{\if\Segno--\fi1}% +\MultVect\@sPun by 0,\@tempA to\@vPun +\DirOfVect\@vPun to\@Dir +\AddVect\@sPun and #1 to \@sPun +\GetCoord(\@sPun)\@tdX\@tdY +\@tdD\if\Segno--\fi\DeltaGradi\p@ +\@tdD=.5\@tdD \Numero\@tempB\@tdD +\DirFromAngle\@tempB to\@Dird +\MultVect\@Dir by*\@Dird to\@Dir +\GetCoord(\@Dir)\@xnum\@ynum +\put(\@tdX,\@tdY){\vector(\@xnum,\@ynum){0}}% end point arrowt ip +\@tdE =\DeltaGradi\p@ +\advance\@tdA -2\@tdE \Numero\@gradi\@tdA +\CopyVect#1to\@Cent \GetCoord(\@pPun)\@pPunX\@pPunY +\SubVect\@Cent from\@pPun to \@V +\edef\@tempa{\if\Segno-\else-\fi\@ne}% +\MultVect\@V by0,\@tempa to\@vPun +\@tdE\if\Segno--\fi\DeltaGradi\p@ +\Numero\@tempB{0.5\@tdE}% +\DirFromAngle\@tempB to\@Dird +\MultVect\@vPun by\@Dird to\@vPun% corrects the starting point +\DirOfVect\@vPun to\@Dir\GetCoord(\@Dir)\@xnum\@ynum +\put(\@pPunX,\@pPunY){\vector(\@xnum,\@ynum){0}}% starting point arrow tip +\edef\@tempa{\if\Segno--\fi\DeltaGradi}% +\DirFromAngle\@tempa to \@Dir +\SubVect\@Cent from\@pPun to\@V +\MultVect\@V by\@Dir to\@V +\AddVect\@Cent and\@V to\@pPun +\GetCoord(\@pPun)\@pPunX\@pPunY +\@@Arc +\strokepath\ignorespaces}% +\def\CurveBetween#1and#2WithDirs#3and#4{% +\StartCurveAt#1WithDir{#3}\relax +\CurveTo#2WithDir{#4}\CurveFinish\ignorespaces}% +\def\StartCurveAt#1WithDir#2{% +\begingroup +\GetCoord(#1)\@tempa\@tempb +\CopyVect\@tempa,\@tempb to\@Pzero +\pIIe@moveto{\@tempa\unitlength}{\@tempb\unitlength}% +\GetCoord(#2)\@tempa\@tempb +\CopyVect\@tempa,\@tempb to\@Dzero +\DirOfVect\@Dzero to\@Dzero +\ignorespaces} +\def\ChangeDir<#1>{% +\GetCoord(#1)\@tempa\@tempb +\CopyVect\@tempa,\@tempb to\@Dzero +\DirOfVect\@Dzero to\@Dzero +\ignorespaces} +\def\CurveFinish{\strokepath\endgroup\ignorespaces}% +\def\FillCurve{\fillpath\endgroup\ignorespaces} +\def\CurveEnd{\fillstroke\endgroup\ignorespaces} +\def\CbezierTo#1WithDir#2AndDists#3And#4{% +\GetCoord(#1)\@tX\@tY \MakeVectorFrom\@tX\@tY to\@Puno +\GetCoord(#2)\@tX\@tY \MakeVectorFrom\@tX\@tY to \@Duno +\DirOfVect\@Duno to\@Duno +\ScaleVect\@Dzero by#3to\@Czero \AddVect\@Pzero and\@Czero to\@Czero +\ScaleVect\@Duno by-#4to \@Cuno \AddVect\@Puno and\@Cuno to \@Cuno +\GetCoord(\@Czero)\@XCzero\@YCzero +\GetCoord(\@Cuno)\@XCuno\@YCuno +\GetCoord(\@Puno)\@XPuno\@YPuno +\pIIe@curveto{\@XCzero\unitlength}{\@YCzero\unitlength}% + {\@XCuno\unitlength}{\@YCuno\unitlength}% + {\@XPuno\unitlength}{\@YPuno\unitlength}% +\CopyVect\@Puno to\@Pzero +\CopyVect\@Duno to\@Dzero +\ignorespaces}% +\def\CbezierBetween#1And#2WithDirs#3And#4UsingDists#5And#6{% +\StartCurveAt#1WithDir{#3}\relax +\CbezierTo#2WithDir#4AndDists#5And{#6}\CurveFinish} + +\def\@isTension#1;#2!!{\def\@tempA{#1}% +\def\@tempB{#2}\unless\ifx\@tempB\empty\strip@semicolon#2\fi} +\def\strip@semicolon#1;{\def\@tempB{#1}} +\def\CurveTo#1WithDir#2{% +\def\@Tuno{1}\def\@Tzero{1}\relax +\edef\@Puno{#1}\@isTension#2;!!% +\expandafter\DirOfVect\@tempA to\@Duno +\bgroup\unless\ifx\@tempB\empty\GetCoord(\@tempB)\@Tzero\@Tuno\fi +\DistanceAndDirOfVect\@Puno minus\@Pzero to\@Chord and\@DirChord +\MultVect\@Dzero by*\@DirChord to \@Dpzero +\MultVect\@Duno by*\@DirChord to \@Dpuno +\GetCoord(\@Dpzero)\@DXpzero\@DYpzero +\GetCoord(\@Dpuno)\@DXpuno\@DYpuno +\DivideFN\@Chord by2 to\@semichord +\ifdim\@DXpzero\p@=\z@ + \@tdA=1.333333\p@ + \Numero\@KCzero{\@semichord\@tdA}% +\fi +\ifdim\@DYpzero\p@=\z@ + \@tdA=1.333333\p@ + \Numero\@Kpzero{\@semichord\@tdA}% +\fi +\unless\ifdim\@DXpzero\p@=\z@ + \unless\ifdim\@DYpzero\p@=\z@ + \edef\@CosDzero{\ifdim\@DXpzero\p@<\z@ -\fi\@DXpzero}% + \edef\@SinDzero{\ifdim\@DYpzero\p@<\z@ -\fi\@DYpzero}% + \@tdA=\@semichord\p@ \@tdA=1.333333\@tdA + \DividE\@tdA by\@SinDzero\p@ to \@KCzero + \@tdA=\dimexpr(\p@-\@CosDzero\p@)\relax + \DividE\@KCzero\@tdA by\@SinDzero\p@ to \@KCzero + \fi +\fi +\MultiplyFN\@KCzero by \@Tzero to \@KCzero +\ScaleVect\@Dzero by\@KCzero to\@CPzero +\AddVect\@Pzero and\@CPzero to\@CPzero +\ifdim\@DXpuno\p@=\z@ + \@tdA=-1.333333\p@ + \Numero\@KCuno{\@semichord\@tdA}% +\fi +\ifdim\@DYpuno\p@=\z@ + \@tdA=-1.333333\p@ + \Numero\@KCuno{\@semichord\@tdA}% +\fi +\unless\ifdim\@DXpuno\p@=\z@ + \unless\ifdim\@DYpuno\p@=\z@ + \edef\@CosDuno{\ifdim\@DXpuno\p@<\z@ -\fi\@DXpuno}% + \edef\@SinDuno{\ifdim\@DYpuno\p@<\z@ -\fi\@DYpuno}% + \@tdA=\@semichord\p@ \@tdA=-1.333333\@tdA + \DividE\@tdA by \@SinDuno\p@ to \@KCuno + \@tdA=\dimexpr(\p@-\@CosDuno\p@)\relax + \DividE\@KCuno\@tdA by\@SinDuno\p@ to \@KCuno + \fi +\fi +\MultiplyFN\@KCuno by \@Tuno to \@KCuno +\ScaleVect\@Duno by\@KCuno to\@CPuno +\AddVect\@Puno and\@CPuno to\@CPuno +\GetCoord(\@Puno)\@XPuno\@YPuno +\GetCoord(\@CPzero)\@XCPzero\@YCPzero +\GetCoord(\@CPuno)\@XCPuno\@YCPuno +\pIIe@curveto{\@XCPzero\unitlength}{\@YCPzero\unitlength}% + {\@XCPuno\unitlength}{\@YCPuno\unitlength}% + {\@XPuno\unitlength}{\@YPuno\unitlength}\egroup +\CopyVect\@Puno to\@Pzero +\CopyVect\@Duno to\@Dzero +\ignorespaces}% +\def\Curve{\@ifstar{\let\fillstroke\fillpath\Curve@}% +{\let\fillstroke\strokepath\Curve@}} +\def\Curve@(#1)<#2>{% + \StartCurveAt#1WithDir{#2}% + \@ifnextchar\lp@r\@Curve{% + \PackageWarning{curve2e}{% + Curve specifications must contain at least two nodes!\Messagebreak + Please, control your Curve specifications\MessageBreak}}} +\def\@Curve(#1)<#2>{% + \CurveTo#1WithDir{#2}% + \@ifnextchar\lp@r\@Curve{% + \@ifnextchar[\@ChangeDir\CurveEnd}} +\def\@ChangeDir[#1]{\ChangeDir<#1>\@Curve} +\def\Qurve{\@ifstar{\let\fillstroke\fillpath\Qurve@}% +{\let\fillstroke\strokepath\Qurve@}} + +\def\Qurve@(#1)<#2>{% + \StartCurveAt#1WithDir{#2}% + \@ifnextchar\lp@r\@Qurve{% + \PackageWarning{curve2e}{% + Quadratic curve specifications must contain at least + two nodes!\Messagebreak + Please, control your Qurve specifications\MessageBreak}}}% +\def\@Qurve(#1)<#2>{\QurveTo#1WithDir{#2}% + \@ifnextchar\lp@r\@Qurve{% + \@ifnextchar[\@ChangeQDir\CurveEnd}}% +\def\@ChangeQDir[#1]{\ChangeDir<#1>\@Qurve}% +\def\QurveTo#1WithDir#2{% +\edef\@Puno{#1}\DirOfVect#2to\@Duno\bgroup +\DistanceAndDirOfVect\@Puno minus\@Pzero to\@Chord and\@DirChord +\MultVect\@Dzero by*\@Duno to \@Scalar +\YpartOfVect\@Scalar to \@YScalar +\ifdim\@YScalar\p@=\z@ +\PackageWarning{curve2e}% + {Quadratic Bezier arcs cannot have their starting\MessageBreak + and ending directions parallel or antiparallel with\MessageBreak + each other. This arc is skipped and replaced with + a dotted line.\MessageBreak}% + \Dotline(\@Pzero)(\@Puno){2}\relax +\else +\MultVect\@Dzero by*\@DirChord to \@Dpzero +\MultVect\@Duno by*\@DirChord to \@Dpuno +\GetCoord(\@Dpzero)\@DXpzero\@DYpzero +\GetCoord(\@Dpuno)\@DXpuno\@DYpuno +\MultiplyFN\@DXpzero by\@DXpuno to\@XXD +\MultiplyFN\@DYpzero by\@DYpuno to\@YYD +\unless\ifdim\@YYD\p@<\z@\ifdim\@XXD\p@<\z@ +\PackageWarning{curve2e}% + {Quadratic Bezier arcs cannot have inflection points\MessageBreak + Therefore the tangents to the starting and ending arc\MessageBreak + points cannot be directed to the same half plane.\MessageBreak + This arc is skipped and replaced by a dotted line\MessageBreak}% + \Dotline(\@Pzero)(\@Puno){2}\fi +\else +\edef\@CDzero{\@DXpzero}\relax +\edef\@SDzero{\@DYpzero}\relax +\edef\@CDuno{\@DXpuno}\relax +\edef\@SDuno{\@DYpuno}\relax +\MultiplyFN\@SDzero by\@CDuno to\@tempA +\MultiplyFN\@SDuno by\@CDzero to\@tempB +\edef\@tempA{\strip@pt\dimexpr\@tempA\p@-\@tempB\p@}\relax +\@tdA=\@SDuno\p@ \@tdB=\@Chord\p@ \@tdC=\@tempA\p@ +\edef\@tempC{\strip@pt\dimexpr \@tdA*\@tdB/\@tdC}\relax +\MultiplyFN\@tempC by\@CDzero to \@XC +\MultiplyFN\@tempC by\@SDzero to \@YC +\ModOfVect\@XC,\@YC to\@KC +\ScaleVect\@Dzero by\@KC to\@CP +\AddVect\@Pzero and\@CP to\@CP +\GetCoord(\@Pzero)\@XPzero\@YPzero +\GetCoord(\@Puno)\@XPuno\@YPuno +\GetCoord(\@CP)\@XCP\@YCP +\@ovxx=\@XPzero\unitlength \@ovyy=\@YPzero\unitlength +\@ovdx=\@XCP\unitlength \@ovdy=\@YCP\unitlength +\@xdim=\@XPuno\unitlength \@ydim=\@YPuno\unitlength + \pIIe@bezier@QtoC\@ovxx\@ovdx\@ovro + \pIIe@bezier@QtoC\@ovyy\@ovdy\@ovri + \pIIe@bezier@QtoC\@xdim\@ovdx\@clnwd + \pIIe@bezier@QtoC\@ydim\@ovdy\@clnht + \pIIe@moveto\@ovxx\@ovyy + \pIIe@curveto\@ovro\@ovri\@clnwd\@clnht\@xdim\@ydim +\fi\fi\egroup +\CopyVect\@Puno to\@Pzero +\CopyVect\@Duno to\@Dzero +\ignorespaces} + +% \end{macrocode} +%\iffalse +% +%\fi +% \Finale +% \endinput + +%^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/macros/latex/contrib/curve2e/curve2e.pdf b/macros/latex/contrib/curve2e/curve2e.pdf new file mode 100644 index 0000000000..519ee31679 Binary files /dev/null and b/macros/latex/contrib/curve2e/curve2e.pdf differ diff --git a/macros/latex/contrib/curve2e/ltxdoc.cfg b/macros/latex/contrib/curve2e/ltxdoc.cfg new file mode 100644 index 0000000000..3593bb1e5f --- /dev/null +++ b/macros/latex/contrib/curve2e/ltxdoc.cfg @@ -0,0 +1,7 @@ +%% +%% This is file `ltxdoc.cfg', + +\AtBeginDocument{\OnlyDescription} + +%% +%% End of file `ltxdoc.cfg'. -- cgit v1.2.3