From b3e238cd492685a317cf453cbac604541622a450 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 4 Dec 2012 22:14:04 +0000 Subject: mfpic (4dec12) git-svn-id: svn://tug.org/texlive/trunk@28444 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/source/generic/mfpic/grafbase.dtx | 1211 +++++++++++++++++--- Master/texmf-dist/source/generic/mfpic/mfpic.dtx | 525 ++++++--- Master/texmf-dist/source/generic/mfpic/mfpic.ins | 11 +- 3 files changed, 1400 insertions(+), 347 deletions(-) (limited to 'Master/texmf-dist/source/generic') diff --git a/Master/texmf-dist/source/generic/mfpic/grafbase.dtx b/Master/texmf-dist/source/generic/mfpic/grafbase.dtx index a309f242f6e..8b7346720dd 100644 --- a/Master/texmf-dist/source/generic/mfpic/grafbase.dtx +++ b/Master/texmf-dist/source/generic/mfpic/grafbase.dtx @@ -1,17 +1,17 @@ % \iffalse % File: grafbase.dtx -% A part of mfpic 1.06 2011/03/08 +% A part of mfpic 1.10 2012/12/03 % % ------------------------------------------------------------------- % -% Copyright 2002--2011, Daniel H. Luecking +% Copyright 2002--2012, Daniel H. Luecking % % Mfpic may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3b of this license or (at % your option) any later version. The latest version of this license is in % -% and version 1.3b or later is part of all distributions of LaTeX version -% 2003/12/01 or later. +% and version 1.3c or later is part of all distributions of LaTeX version +% 2008/12/01 or later. % % Mfpic has maintenance status "author-maintained". The Current Maintainer % is Daniel H. Luecking. There are several Base Interpreters: plain TeX, LaTeX, @@ -19,7 +19,7 @@ % %<*driver> \ProvidesFile{grafbase.dtx} - [2011/03/08 v1.06. Metafont/post macros to interface with mfpic.]% + [2012/12/03 v1.10. Metafont/post macros to interface with mfpic.]% \documentclass{ltxdoc} \usepackage{docmfp} @@ -51,6 +51,7 @@ \renewcommand\|{${}\mathrel{|}{}$} \makeatletter +\let\HD@SetMacroIndent\@gobble \newcommand\bsl{{\mytt\@backslashchar}} % Stupid lists! \def\@listi{\leftmargin\leftmargini @@ -113,7 +114,7 @@ % %\fi % -% \CheckSum{1473} +% \CheckSum{1631} % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z @@ -146,14 +147,17 @@ % This file documents the \grafbase{} source code. The user manual for % \mfpic{} is distributed as \file{mfpic-doc.pdf}, produced from % \file{mfpic-doc.tex}. An introductory guide to \mfpic{} is available -% in \file{mfpguide.pdf}, produced from \file{mfpguide.pdf} +% in \file{mfpguide.pdf}, produced from \file{mfpguide.tex} % \end{abstract} % % \StopEventually{\PrintIndex} % \tableofcontents % +% +% % \section{Introduction}\label{intro} % +% % \subsection{Identification and checks}\label{checks} % % \DescribeVariable{grafbaseversion} We use \mfc{grafbaseversion} to @@ -187,13 +191,14 @@ fi boolean grafbase; grafbase := true; string fileversion, filedate; -fileversion := "1.06"; filedate := "2011/02/25"; +fileversion := "1.10"; filedate := "2012/12/03"; message " Loading grafbase macros, version " & fileversion & ", " & filedate & "."; message " "; -def GBmsg expr s = message "Grafbase (" & jobname & "): " & s; enddef; +def GBmsg expr s = message "Grafbase (" & jobname & "): " & s; +enddef; def GBwarn expr s = GBmsg "Warning, " & s; enddef; def GBerrmsg (expr s) expr t = errhelp t; errmessage "Grafbase (" & jobname & "): " & s; errhelp ""; @@ -236,7 +241,7 @@ def checkversions (expr g)= fi enddef; -checkversions (106); +checkversions (110); % \end{macrocode} % @@ -298,29 +303,30 @@ enddef; % In \MF{} `\mfc{color X}' is an identifier (presumably unknown) with the % base name \mfc{color} and suffix \mfc{X}. % \begin{macrocode} -boolean METAPOST; -METAPOST := known color Geamparalele din Babadag; +boolean METAFONT, METAPOST; +METAPOST := known color Carl Philipp Emanuel Bach; +if METAPOST: METAFONT := false; else: METAFONT := true; fi %<*MF> if METAPOST: GBerrmsg ("wrong compiler.") - "This file is for Metafont. For Metapost use grafbase.mp."; + "This file is for Metafont. For Metapost, use grafbase.mp."; fi % %<*MP> -if not METAPOST: +if METAFONT: GBerrmsg ("wrong compiler.") - "This file is for Metapost. For Metafont use grafbase.mf."; + "This file is for Metapost. For Metafont, use grafbase.mf."; fi % \end{macrocode} % % \MP{} now exists in a couple of slightly incompatible versions. -% Versions 1.000 and later (beta versions 0.900 also) have native support for -% \texttt{CMYK} colors with a \mfc{cmykcolor} data type. It also -% supports grayscale colors (i.e., \mfc{withcolor} will accept a numeric -% expression), and has the alias \mfc{rgbcolor} for \mfc{color}. +% Versions 1.000 and later (beta versions 0.9xx also) have native support for +% \texttt{CMYK} colors with a \mfc{cmykcolor} data type. They also +% support grayscale colors (i.e., \mfc{withcolor} will accept a numeric +% expression), and have the alias \mfc{rgbcolor} for \mfc{color}. % It also has a means to set the name of the output file: the % \mfc{filenametemplate} command. In versions 1.2 and later, this is % deprecated in favor of setting the internal string variable @@ -351,6 +357,7 @@ fi % % \end{macrocode} % +% % \subsection{Setting up the font, \MF{} only}\label{font} % % Font-related housekeeping is only for \MF{}. \MF{} only produces @@ -360,9 +367,10 @@ fi % \DescribeVariable{GBgeneric} % We intercept the \mfc{mode} variable before \mfc{mode_setup} can set % \mfc{proof} mode. We used to set \mfc{mode := cx} (and later -% \mfc{ljfour}) if it was unknown. For a while we just issued an error -% message. In this version we define a 600dpi mode called \mfc{GBgeneric} -% as a fallback (neither \gbc{mode} nor \gbc{localfont} known). +% \mfc{ljfour}) if \mfc{mode} was unknown. For a while we just issued an +% error message. In this version we define a 600dpi mode called +% \mfc{GBgeneric} as a fallback (neither \gbc{mode} nor \gbc{localfont} +% known). % % The font identifier and coding scheme are just for information and end % up as comments in the \file{.tfm} file (in all capitals). The design @@ -430,6 +438,7 @@ interim warningcheck := 0; % \end{macrocode} % +% % \subsection{Initializations}\label{init} % % \VariableIndex{unitlen} @@ -460,15 +469,17 @@ yneg := 0; ypos := 10; % We support both degrees and radians for angles. In \MF, one degree is % the unit of angle. % \DescribeVariable{radian} -% One radian is $180/\pi$ degrees. We also define \gbc{pi} so a user can say -% \gbc{90} or \gbc{90deg} or \gbc{pi/2*radian} +% One radian is $180/\pi$ degrees. We also define \gbc{pi} so a user can +% say \gbc{pi/2*radian} for almost the same effect as \gbc{90deg}. % \DescribeVariable{pi} -% for the same effect. Actually, not quite: because of \MF{}'s precision -% limits, the latter is about 90.00025 degrees. \MF{}'s precision is 16 -% binary places, or slightly under 5 decimals. The accuracy of \gbc{pi} -% and \gbc{radian} is the maximum possible. If we \emph{define} -% \gbc{radian} to be \gbc{90/(pi/2)} or \gbc{180/pi} the value of -% \gbc{pi/2*radian} is even less accurate. +% But not quite: because of \MF{}'s precision limits, the former is about +% 90.00025 degrees. \MF{}'s precision is 16 binary places, or slightly +% under 5 decimals. The accuracy of \gbc{pi} and \gbc{radian} below is the +% maximum possible. If we \emph{define} \gbc{radian} by its mathematical +% definition \gbc{radian:=180/pi}, then \gbc{radian} and formulas +% containing it are even less accurate. (Coincidentally, defining +% \gbc{radian} as below, and then \gbc{pi := 180/radian} produces exactly +% the same value for \gbc{pi} as below.) % \begin{macrocode} newinternal deg, pi, radian; deg := 1; pi := 3.14159; @@ -500,7 +511,7 @@ numeric degree; degree := deg; % % \VariableIndex{hatchwd} % The default \gbc{hatchwd} used to be larger, but it seemed ugly to me. -% (Backward compatibility? What's that?). +% (Backward compatibility---what's that?). % \begin{macrocode} newinternal penwd; penwd := 0.5pt; pen drawpen; @@ -572,6 +583,7 @@ boolean showbbox; showbbox := false; % \end{macrocode} % +% % \subsubsection{Colors}\label{colors} % % Of course colors are only recognized by \MP. The colors \mfc{black}, @@ -595,7 +607,7 @@ let cmykcolor = numeric; black := 0; white := 1; def withcolor text t = enddef; % -%if not has_cmyk: let rgbcolor = color; let cmykcolor = color; fi +%if not has_cmyk: let rgbcolor = color; let cmykcolor = color; fi def _wc_ = withcolor enddef; % \end{macrocode} @@ -653,32 +665,61 @@ enddef; % two. In \MF{} \gbc{white} is a numeric and \gbc{cmyk} returns a % numeric, so these can be used with \MF{}, and both produce the same % result. -% -% \DescribeRoutine{grayscalegray} -% The grayscale version should return a numeric in recent \MP{}, so -% it needs a different definition for early \MP{}. Thus, it occurs -% in the conditional code. Oddly, its definition is the same for \MF{} -% and recent \MP{}. % \begin{macrocode} vardef rgbgray (expr g) = (snapto g) * white enddef; vardef cmykgray (expr g) = cmyk(0,0,0,1 - snapto g) enddef; % \end{macrocode} % +% +% \DescribeRoutine{colorchoice} +% The \gbc{colorchoice} function (like \cs{mathchoice} in \TeX{}, after +% which it was named) returns one of four bits of code: \gbc{D} (default) +% if the first argument is unknown or not one of the recognized color +% models, \gbc{N} if it is numeric, \gbc{R} if it is \mfc{rgbcolor}, and +% \gbc{C} if it is \mfc{cmykcolor}. These arguments have to be \mfc{text}: +% if they were `\mfc{expr}' \MP{} would try to evaluate them, with +% possible errors since some of them apply functions that are not relevant +% to the other types. +% +% Since this is mostly used to return values inside vardef's, it is +% important this not be followed by a semicolon. If it is used in +% another context, semicolons would normally be part of the arguments. +% \begin{macrocode} +%<*MP> +def colorchoice (expr clr) (text D)(text N)(text R)(text C) = + if unknown clr: D + elseif numeric clr: N + elseif rgbcolor clr: R + elseif cmykcolor clr: C + else: D + fi +enddef; + +% \end{macrocode} % In recent \MP{}, all the color functions are essentially no-ops. In % early \MP{}, they all return an \opt{rgb} color expression. In \MF{} % they all return a numeric. It is easiest if we simply separate the three -% cases and write the code for each, rather than load all the functions -% with three-way booleans (often containing nested booleans). +% cases (MF, old MP and recent MP) and write the code for each, rather +% than load all the functions with three-way booleans (often containing +% nested booleans). % +% \DescribeRoutine{gray} +% \DescribeRoutine{cmyk} % For all three engines we require a definition of the color functions % \gbc{gray(g)}, \gbc{rgb(r,g,b)}, and \gbc{cmyk(c,m,y,k)}, as well as -% conversion functions \gbc{makegray(x)}, \gbc{makergb(x)}, and -% \gbc{makecmyk(x)}, and the boolean \gbc{iscolor clr}. The first three -% have to return numerics for \MF{}, colors for early \MP{}, and the -% associated color type for recent \MP{}. +% conversion functions (see below), and the boolean function +% \gbc{iscolor}. The first three have to return numerics for \MF{}, +% colors for early \MP{}, and the associated color type for recent \MP{}. +% We delay the definition of \gbc{rgb} because it only requires +% distinguishing \MF{} from \MP. +% +% \DescribeRoutine{grayscalegray} +% The grayscale version should return a numeric in recent \MP{}, so +% it needs a different definition for early \MP{}. Thus, it occurs +% in the conditional code. Oddly, its definition is the same for \MF{} +% and recent \MP{}. % \begin{macrocode} -%<*MP> if has_cmyk : vardef grayscalegray (expr g) = snapto g enddef; vardef gray (expr g) = grayscalegray (g) enddef; @@ -686,27 +727,6 @@ if has_cmyk : (snapto c, snapto m, snapto y, snapto k) enddef; -% \end{macrocode} -% -% \DescribeRoutine{colorchoice} -% The \gbc{colorchoice} function (like \cs{mathchoice} in \TeX{}, after -% which it was named) returns one of four bits of code: \gbc{D} (default) -% if the first argument is unknown or not one of the recognized color -% models, \gbc{N} if it is numeric, \gbc{R} if it is \mfc{rgbcolor}, and -% \gbc{C} if it is \mfc{cmykcolor}. These arguments have to be \mfc{text}: -% if they were `\mfc{expr}' \MP{} would try to evaluate them, with -% possible errors since some of them apply functions that are not relevant -% to the other types. -% \begin{macrocode} - def colorchoice (expr clr) (text D)(text N)(text R)(text C) = - if unknown clr: D - elseif numeric clr: N - elseif rgbcolor clr: R - elseif cmykcolor clr: C - else: D - fi - enddef; - % \end{macrocode} % % \DescribeRoutine{makecmyk} @@ -714,8 +734,8 @@ if has_cmyk : % \DescribeRoutine{makegray} % In \gbc{makecmyk} and all the other `\gbc{make}' conversions, the % default is to return black in the appropriate model, numerics produce -% gray, and cmyk or rgb is either retained unchanged or converted to the -% appropriate model. +% gray in the appropriate model, and cmyk or rgb is either retained +% unchanged or converted to the appropriate model. % % \DescribeRoutine{iscolor} % A variable is taken to be a color if it can validly follow @@ -729,14 +749,14 @@ if has_cmyk : enddef; vardef makergb primary clr = colorchoice (clr)(rgbblack)(rgbgray(clr))(clr) - (cmyktorgb(cyanpart clr, magentapart clr, yellowpart clr, - blackpart clr)) + (cmyktorgb(cyanpart clr, magentapart clr, + yellowpart clr, blackpart clr)) enddef; vardef makegray primary clr = colorchoice (clr)(grayscaleblack)(grayscalegray(clr)) (rgbtogray (redpart clr, greenpart clr, bluepart clr)) - (cmyktogray(cyanpart clr, magentapart clr, yellowpart clr, - blackpart clr)) + (cmyktogray(cyanpart clr, magentapart clr, + yellowpart clr, blackpart clr)) enddef; vardef iscolor expr clr = (rgbcolor clr) or (cmykcolor clr) or (numeric clr) or (boolean clr) @@ -744,10 +764,13 @@ if has_cmyk : else: % \end{macrocode} % -% \DescribeRoutine{colorchoice} -% In early \MP{} \gbc{colorchoice} is a three-way choice, since -% \mfc{cmykcolor} is not an available data type, but numeric can still be -% interpreted as a gray. +% In early \MP{} \gbc{colorchoice} is only a three-way choice, since +% \mfc{cmykcolor} is not a data type, but numeric can still be +% interpreted as a gray. For a numeric or an actual rgbcolor, the first or +% second branch would be taken. If \gbc{clr} is neither of those then +% \mfc{cmykcolor}, being equal to \mfc{rgbcolor}, would also be false. +% Therefore, in the context of early \MP{}, it is irrelevant what goes in +% the last argument, so we leave it empty. % % \DescribeRoutine{makecmyk} % \DescribeRoutine{makergb} @@ -762,19 +785,12 @@ else: vardef gray (expr g) = rgbgray(g) enddef; vardef grayscalegray (expr g) = rgbgray(g) enddef; vardef cmyk (expr c, m, y, k) = rgb (1-c-k, 1-m-k, 1-y-k) enddef; - def colorchoice (expr clr) (text D)(text N)(text R) = - if unknown clr: D - elseif numeric clr: N - elseif rgbcolor clr: R - else: D - fi - enddef; vardef makergb primary clr = - colorchoice (clr)(rgbblack)(rgbgray(clr))(clr) + colorchoice (clr)(rgbblack)(rgbgray(clr))(clr)() enddef; vardef makegray primary clr = colorchoice (clr)(rgbblack)(rgbgray(clr)) - (rgbtogray (redpart clr, greenpart clr, bluepart clr)) + (rgbtogray (redpart clr, greenpart clr, bluepart clr))() enddef; def makecmyk = makergb enddef; vardef iscolor expr clr = (color clr) enddef; @@ -783,7 +799,7 @@ fi % % \end{macrocode} % -% \DescribeMacro{knowncolor} +% \DescribeRoutine{knowncolor} % Once we have \gbc{iscolor} all we need to do is add a test for % \mfc{known} to get this boolean test. % \begin{macrocode} @@ -808,7 +824,7 @@ vardef iscolor expr clr = (color clr) enddef; % % \end{macrocode} % -% \DescribeRoutine{forcecolor} +% \DescribeRoutine{forceclr} % \DescribeRoutine{named} % This is only used in the \gbc{named} function to force a color. In % \MF{} the tests are all `\mfc{if numeric}'. In early \MP{} `\mfc{if @@ -870,6 +886,7 @@ enddef; % \end{macrocode} % +% % \subsection{Arrays}\label{arrays} % % \gbc{ClipPath} is a typical example of an array. Arrays are based on the @@ -999,6 +1016,7 @@ enddef; % \end{macrocode} % +% % \subsection{Utilities}\label{utilities} % % \DescribeRoutine{chpair} @@ -1025,13 +1043,14 @@ vardef chpair (text proc) (expr p) = (proc (xpart p), proc (ypart p)) enddef; -vardef floorpair (expr p) = (floor (xpart p), floor (ypart p)) enddef; -vardef ceilingpair (expr p) = - (ceiling (xpart p), ceiling (ypart p)) +vardef floorpair (expr p) = (floor (xpart p), floor (ypart p)) +enddef; +vardef ceilingpair (expr p) = (ceiling (xpart p), ceiling (ypart p)) enddef; %<*MF> -def hroundpair (expr p) = (hround (xpart p), hround (ypart p)) enddef; +def hroundpair (expr p) = (hround (xpart p), hround (ypart p)) +enddef; vardef goodpair (expr p) = hroundpair(p.t_) enddef; % @@ -1090,7 +1109,8 @@ enddef; % things, twice the area of the triangle with two sides $z\sb1$ and % $z\sb2$. It is used only in \gbc{mkconvex}. % \begin{macrocode} -primarydef Z xprod W = (xpart Z * ypart W - xpart W * ypart Z) enddef; +primarydef Z xprod W = (xpart Z * ypart W - xpart W * ypart Z) +enddef; % \end{macrocode} % @@ -1262,7 +1282,7 @@ def endimage = enddef; def makeimage (suffix name) (expr refpt) = - setpair (_image_reference_point) zconv(refpt); + setpair (_image_reference_point) zconv (refpt); setpicture (name) beginimage enddef; def concludeimage = @@ -1481,6 +1501,8 @@ enddef; % \end{macrocode} % +% +% % \section{The \grafbase{} Coordinate System}\label{coordinate} % % We need to make a distinction between graph units, sharped units, and @@ -1526,6 +1548,7 @@ enddef; % want the lower left corner of the graph space to have device coordinates % $(0,0)$. % +% % \subsection{The main transforms}\label{ztr} % % \DescribeVariable{vtr} @@ -1621,6 +1644,7 @@ vardef invvconv (expr v) = v transformed (inverse vtr) enddef; % \end{macrocode} % +% % \subsection{The \gbc{mfpic} environment}\label{mfpic} % % \DescribeRoutine{active_plane} @@ -1643,7 +1667,7 @@ def active_plane = currentpicture enddef; % % If \gbc{underlaylabels} is true, we try to make them part of the % background, adding them to the picture variable \gbc{background_labels}. -% Just before shipout, the picture is placed on top. +% Just before shipout, the picture is placed on top of these labels. % % If \gbc{overlaylabels} is \gbc{true}, we try to make labels in \MP{} % behave the same as labels in \TeX{} (for \mfpic) by adding the labels @@ -1695,8 +1719,8 @@ enddef; % \mfpic. % % \DescribeRoutine{bounds} -% This used to be for compatibility also, but I decided it was a -% convenient abbreviation, so \mfpic{} uses it now. +% This also used to be unused, for compatibility only, but I decided it was a +% convenient abbreviation and \mfpic{} uses it again. % \begin{macrocode} def mfpicenv = enddef; def endmfpicenv = enddef; @@ -1844,6 +1868,7 @@ enddef; % \end{macrocode} % % +% % \section{Text}\label{text} % % In the \MP{} version, \gbc{label_adjust}, \gbc{label_sep} and @@ -1879,6 +1904,7 @@ label_sep := 0; labelpath_sep := 0; % \end{macrocode} % +% % \subsection{Placement of text, \MP{} only}\label{placement} % % \DescribeRoutine{newgblabel} @@ -1996,6 +2022,7 @@ enddef; % \end{macrocode} % +% % \subsection{Decorating the text, \MF{} or \MP{}}\label{decorating} % % The three macros \gbc{textrect}, \gbc{textoval} and \gbc{textellipse} @@ -2111,7 +2138,8 @@ vardef textrectx (expr a, b, c, rot, xy, lbl, rad, loc) = fi readjustdims (ll, ur) (label_sep - labelpath_sep); - invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f)) shifted loc + invvconv (thegblabel (ref_shift(a, b, c, ll, ur), rot, f)) + shifted loc enddef; % \end{macrocode} @@ -2160,7 +2188,8 @@ vardef xellipse (expr aspect, a, b, c, r, xy, lbl, mult, loc) = f := ellipse (cc, aa, bb, 0); fi readjustdims (ll, ur) (label_sep - labelpath_sep); - invvconv (thegblabel (ref_shift(a, b, c, ll, ur), r, f)) shifted loc + invvconv (thegblabel (ref_shift(a, b, c, ll, ur), r, f)) + shifted loc fi enddef; @@ -2197,6 +2226,7 @@ enddef; % \end{macrocode} % % +% % \section{Additional Functions}\label{functions} % % Complex variable functions are provided, which interpret a pair $(x, y)$ @@ -2214,8 +2244,12 @@ enddef; % in \MF.) % % The value \gbc{eps/2 + epsilon} is the smallest value with -% reciprocal less than \mfc{infinity}. I set \gbc{nottoosmall} a speck -% bigger to ensure that the same is true of \gbc{2*(nottoosmall/2)}. +% reciprocal less than \mfc{infinity}. I set \gbc{nottoosmall} to +% \gbc{eps/2 + 2epsilon} to ensure that the same is true of +% \gbc{2*(nottoosmall/2)}. This is probably not necessary as +% \mfc{epsilon/2} should round up to \mfc{epsilon} and not be lost. But +% it also ensures that \gbc{nottoosmall} equals \gbc{2*(nottoosmall/2)}, +% which could be useful. % % We set \gbc{secd x = 1/(cosd x)} unless \gbc{cosd x} is less than % \gbc{reallysmall}, then we set it equal to \gbc{1/reallysmall}. We do a @@ -2330,9 +2364,9 @@ vardef radians (expr t) = t/radian enddef; % \RoutineIndex{invcos}\gbc{invcos} and \RoutineIndex{invtan}\gbc{invtan}) % that return angles in radians. % \begin{macrocode} -vardef invcos primary X = (acos X)/radian enddef; -vardef invsin primary X = (asin X)/radian enddef; -vardef invtan primary X = (atan X)/radian enddef; +vardef invcos primary X = radians (acos X) enddef; +vardef invsin primary X = radians (asin X) enddef; +vardef invtan primary X = radians (atan X) enddef; % \end{macrocode} % @@ -2346,10 +2380,10 @@ vardef invtan primary X = (atan X)/radian enddef; % \begin{macrocode} vardef exp primary X = mexp (256 * X) enddef; vardef ln primary X = (mlog X) / 256 enddef; -def log = ln enddef; +vardef log primary X = ln (X) enddef; vardef logbase (expr B) primary X = (mlog X)/(mlog B) enddef; -def logtwo = logbase( 2) enddef; -def logten = logbase(10) enddef; +vardef logtwo primary X = logbase( 2) (X) enddef; +vardef logten primary X = logbase(10) (X) enddef; % \end{macrocode} % @@ -2437,15 +2471,32 @@ enddef; % These give some of the more basic functions of standard complex % analysis: \RoutineIndex{Arg}\gbc{Arg}, \RoutineIndex{Log}\gbc{Log}, % \RoutineIndex{cis}\gbc{cis}, \RoutineIndex{zexp}\gbc{zexp}, -% \RoutineIndex{sgn}\gbc{sgn}, and \RoutineIndex{conj}\gbc{conj}. +% \RoutineIndex{sgn}\gbc{sgn}, \RoutineIndex{zsqrt}\gbc{zsqrt} and +% \RoutineIndex{conj}\gbc{conj}. % \begin{macrocode} vardef Arg primary Z = (angle Z)/radian enddef; vardef Log primary Z = (ln (abs Z), Arg Z) enddef; vardef cis primary T = dir (T*radian) enddef; vardef zexp primary Z = (exp (xpart Z)) * cis (ypart Z) enddef; -vardef sgn primary Z = if not (Z = origin): unitvector fi Z enddef; +vardef sgn primary Z = if not (Z = origin): unitvector fi Z +enddef; +vardef zsqrt primary Z = + if Z = origin: origin else: sqrt(abs(Z)) * dir ((angle Z)/2) fi +enddef; vardef conj primary Z = (xpart Z, -ypart Z) enddef; +% \end{macrocode} +% +% DescribeRoutine{zmul} +% Unfortunately, while \MF{} will happily add and subtract pairs, it +% will not multiply or divide them without help. We provide alternatives +% \DescribeRoutine{zdiv} here. +% \begin{macrocode} +primarydef Z zmul W = Z zscaled W enddef; +primarydef Z zdiv W = + Z zmul ( unitvector (conj W) / (abs W) ) +enddef; + % \end{macrocode} % % \DescribeRoutine{Moebius} @@ -2454,11 +2505,19 @@ vardef conj primary Z = (xpart Z, -ypart Z) enddef; % in Euclidean geometry. Its mathematical definition (all variables are % complex numbers): % \[ -% M_a(z) = \frac{z + a}{1 - \bar az} +% M_a(z) = \frac{z + a}{1 + \bar az} % \] +% Its inverse is $M_{-a}$. +% % \DescribeRoutine{pshdist} % Related to \gbc{Moebius} is the pseudohyperbolic metric. The distance -% between $z$ and $w$ in this metric is $|z-w|/|1 - \bar wz|$. +% between $z$ and $w$ in this metric is $|z-w|/|1 - \bar wz|$. There is +% \DescribeRoutine{pshdist_hp} +% also a version of this for the upper half-plane: $|z-w|/|z-\bar w|$. +% +% Closely related to all this is Kelvin transform. In complex notation +% it is simply $1/\bar z = z/|z|^2$. The term ``Kelvin transform'' is +% normally only used in real variables (of any dimension greater than 1). % \begin{macrocode} vardef Moebius (expr A) primary Z = save _D; pair _D; @@ -2466,6 +2525,17 @@ vardef Moebius (expr A) primary Z = (Z + A)/(abs _D) rotated (- angle _D) enddef; vardef pshdist (expr Z,W) = abs(Moebius(-W)(Z)) enddef; +vardef pshdist_hp (expr Z,W) = abs(Z-W)/abs(Z-conj(W)) enddef; +vardef kelvin (expr Z) = + save tmp_; tmp_ = abs(Z); + if tmp_ = 0: + (infinity, infinity) + elseif tmp_ < reallysmall: + infinity*unitvector Z + else: + (1/tmp_)*unitvector Z + fi +enddef; % \end{macrocode} % @@ -2485,6 +2555,13 @@ def id (expr x) = x enddef; % integer (that is, satisfy \mfc{x=floor x}). Here we redefine % \prog{plain}'s \mfc{**}, intercepting the case of a positive integer % power of an integer. +% +% There are some negative powers, and some integer powers of nonintegers +% that can also be calculated exactly within \MF{}'s limited precision, +% but it is difficult to determine those cases programmatically. Computing +% every integer power by repeated multiplication or division might +% actually reduce accuracy in the nonexact cases, so we limit ourselves to +% this one special case. % \begin{macrocode} primarydef x**y = if y=2: x*x @@ -2497,6 +2574,7 @@ let ^ = **; % \end{macrocode} % +% % \section{Coordinate Systems and Transformations}\label{systems} % % \DescribeVariable{T_stack} @@ -2532,6 +2610,7 @@ def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef; % \end{macrocode} % +% % \subsection{Coordinate changes}\label{changes} % % \DescribeRoutine{apply_t} @@ -2545,7 +2624,8 @@ def ecoords = hide ( T_pop (ztr); vtr := vectorpart ztr ) enddef; % phrase which, were it to follow a path, would produce a transformed % path. Knuth calls such a phrase a \emph{transformer}. % \begin{macrocode} -vardef vectorpart primary T = T shifted -(origin transformed T) enddef; +vardef vectorpart primary T = T shifted -(origin transformed T) +enddef; def apply_t (text Transformer) = ztr := identity Transformer transformed ztr; @@ -2589,6 +2669,7 @@ def boost primary X = zslant (cosh X, sinh X) enddef; % \end{macrocode} % +% % \subsection{Path transformation}\label{transformation} % % These are functions that accept and return a path in graph coordinates. @@ -2797,8 +2878,10 @@ enddef; % \end{macrocode} % % +% % \section{Picture-level Operations}\label{picture} % +% % \subsection{Bitwise logical operations}\label{logical} % % None of these operations are available in \MP. Mostly these are used by @@ -2905,6 +2988,7 @@ enddef; % % \end{macrocode} % +% % \subsection{Producing and modifying pictures}\label{pictures} % % Here we define some slightly higher level commands that make use (in \MF) @@ -2935,12 +3019,10 @@ enddef; % \gbc{active_plane}, we have eliminated that parameter from % \gbc{coloraddon}. % -% \DescribeRoutine{_orto} -% This version of \gbc{orto} saves memory by passing \emph{both} -% parameters by name. This also allows the application of \gbc{mono} to -% both parameters. In addition to \gbc{coloraddon}, it is used in -% \gbc{shade} and \gbc{tess}. -% \DescribeRoutine{_subto} +% The command \gbc{_orto} is like \gbc{orto}, but saves memory by passing +% \emph{both} parameters by name. This also allows the application of +% \gbc{mono} to both parameters. In addition to \gbc{coloraddon}, it is +% used in \gbc{shade} and \gbc{tess}. % We also have \gbc{_subto}, an analogous version of \gbc{subto}. % \begin{macrocode} def coloraddto (expr clr) (suffix u) (expr v) = @@ -3020,6 +3102,7 @@ enddef; % \end{macrocode} % +% % \subsection{Clipping}\label{basicclipping} % % \DescribeRoutine{clipto} @@ -3312,9 +3395,9 @@ enddef; % calling routine must make sure that picture is initialized (it need % not be \mfc{nullpicture}). % -% One might do this with two nested loops, but it turns out to be much -% faster (surprisingly much!) to do two separate loops: the second one -% stacking copies of the row built by the first loop. +% One might do this with one loop nested in another, but it turns out to +% be much faster (surprisingly much!) to do two separate loops: the second +% one stacking copies of the row built by the first loop. % % We try to do any rounding that might have been forgotten. This code % takes a mode's aspect ratio into account so that (most) calling routines @@ -3351,6 +3434,7 @@ enddef; % \end{macrocode} % +% % \subsection{Hatching}\label{basichatching} % % \DescribeRoutine{thatchf} @@ -3374,7 +3458,7 @@ enddef; % gets one to \gbc{ypart b}. We make the starting value an integer % multiple of \gbc{_sp} to make sure adjacent regions don't have jarringly % misaligned hatch lines. (I guess that's the reason; this algorithm -% predates me.) +% predates my involvement with \mfpic{}.) % \begin{macrocode} def thatchf (suffix v) (expr CT, sp, a, b) = begingroup @@ -3389,6 +3473,178 @@ enddef; % \end{macrocode} % +% +% \subsection{Gradient fills}\label{basicgradient} +% +% \CMP{} cannot do true gradients without some external help. Level-3 +% PostScript permits it, so recent \MP{} could do it by inserting +% appropriate PS prologues and/or \MP{} specials. Doing that runs the +% risk of introducing code not recognized by post-processors that expect +% only what \MP\ natively offers. Therefore, we implement gradients by +% filling a lot of thin regions with a range of different +% colors. +% +% We have to drop down to pretty low-level operations since, before now, +% we didn't need a command that added a colored region to a named +% picture. +% +% For maximum flexibility, all our gradients pass variation in colors as a +% function \mfc{clr} which must be previously \gbc{vardef}-ed and must +% produce a color for each parameter value between $0$ and $1$. +% +% \DescribeRoutine{axialgradientf} +% A linear gradient has colored rectangular strips that vary along a +% single axis. The function parameter of \gbc{axialgradientf} takes one +% variable and produces the color of each strip. \gbc{v} is a known +% picture variable to which the resulting picture will be assigned, +% \gbc{theta} is an angle, \gbc{a} and \gbc{b} are the opposite corners of +% a rectangle. What is returned in \gbc{v} is a rectangular picture +% rotated by \gbc{theta}. +% +% Normally, this is called by the \gbc{axialgradient} command which +% declares the picture variable \gbc{v}, passes its angle parameter +% \gbc{theta}, and computes the bounding box of a cyclic path for \gbc{a} +% and \gbc{b}. The calling command will clip the result to the appropriate +% path. +% +% The calculations with \gbc{signof} is for the same reason as in +% \gbc{thatchf}. The other messy calculations try to cover the rectangle +% exactly with an integer number of strips, with the first and last having +% exactly the colors \gbc{clr(0)} and \gbc{clr(1)}. +% +% If the thickness of the strip is too small, memory problems might +% result and appearence might suffer. Nevertheless we make no attempt to +% enforce a minimum value. +% \begin{macrocode} +def axialgradientf (suffix clr, v) (expr theta, sp, a, b) = + begingroup + save _hh, _sp, _nn, _y; + _hh := ypart b - ypart a; + _sp := signof (_hh) abs(sp); + _nn := emax (1, round (_hh/_sp)); + _sp := _hh/_nn + signof (_hh) epsilon; + _nn := _nn-1; + setpath (_p) rect ((xpart a, 0),(xpart b, _sp)); + _y := ypart a; + for _i = 0 upto _nn: +%<*MF> + if (clr(_i/_nn)) < white : + addto v also shaded (clr(_i/_nn)) ( _p shifted (0,_y)) + rotated theta; + fi +% +%<*MP> + addto v contour (_p shifted (0,_y)) rotated theta + withcolor clr(_i/_nn); +% + _y := _y + _sp; + endfor +% mono (v); + endgroup +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{areagradientf} +% The command \gbc{areagradientf} fills the rectangle determined by +% corners \gbc{a} and \gbc{b} with pixels of dimension \gbc{sp} by +% \gbc{tp}. Each pixel is filled with the color determined by \gbc{clr}. +% This suffix parameter must be the name of a function taking two +% parameters. +% +% The resulting rectangle is built on the picture variable whose name is +% passed as the second parameter \gbc{v}. The calling routine is +% \gbc{areagradient}, which determine the rectangle and initializes +% the picture variable. It passes its other parameters unchanged. +% \begin{macrocode} +def areagradientf (suffix clr, v) (expr sp, tp, a, b) = +begingroup + save _ww, _hh, _sp, _tp, _nn, _mm, _x, _y; + _ww := xpart b - xpart a; + _hh := ypart b - ypart a; + _sp := signof (_ww) abs(sp); + _tp := signof (_hh) abs(tp); + _nn := emax (1, round (_ww/_sp)); + _mm := emax (1, round (_hh/_tp)); + _sp := _ww/_nn + signof (_ww) epsilon; + _tp := _hh/_mm + signof (_hh) epsilon; + _mm := _mm-1; _nn := _nn-1; + setpath (_p) rect (origin,(_sp,_tp)); + _x := xpart a; y_a := ypart a; + for _i = 0 upto _nn: + _y := y_a; + for _j = 0 upto _mm: +%<*MF> + if (clr(_i/_nn,_j/_mm)) < white: + addto v also shaded (clr(_i/_nn,_j/_mm)) (_p shifted (_x,_y)); + fi +% +%<*MP> + addto v contour (_p shifted (_x,_y)) withcolor + clr(_i/_nn,_j/_mm); +% + _y := _y + _tp; + endfor + _x := _x + _sp; + endfor +% mono (v); +endgroup +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{radialgradientf} +% The command \gbc{radialgradientf} fills the a circle determined by +% center \gbc{ctr} and radius \gbc{rad} with concentric circular strips of +% thickness \gbc{sp}. Each strip is filled with the color determined by +% \gbc{clr}. This suffix parameter must be the name of a function of one +% parameter. +% +% This command is called by \gbc{radialgradient}, which determines the +% radius of a circle needed to cover a region and clips the picture +% returned in \gbc{v} to that region. +% \begin{macrocode} +path unitcircle; +unitcircle := fullcircle scaled 2; +def radialgradientf (suffix clr, v) (expr sp, ctr, rad) = + begingroup + save _sp, _r, _nn; + _nn := emax (1, round (rad/sp)); + _sp := rad/_nn + epsilon; + _nn := _nn - 1; + _r := _sp; + % fill the small center circle first +%<*MF> + if (clr(0)) < white : + addto v also shaded (clr(0)) (unitcircle scaled _r shifted ctr); + fi +% +%<*MP> + addto v contour (unitcircle scaled _r shifted ctr) + withcolor clr(0); +% + for _i = 1 upto _nn: +%<*MF> + if (clr(_i/_nn)) < white : + addto v also shaded (clr(_i/_nn)) + (unitcircle scaled (_r + _sp) -- reverse unitcircle scaled _r + --cycle) shifted ctr; + fi +% +%<*MP> + addto v contour + (unitcircle scaled (_r + _sp) -- reverse unitcircle scaled _r + --cycle) shifted ctr withcolor clr(_i/_nn); +% + _r := _r + _sp; + endfor +% mono (v); + endgroup +enddef; + +% \end{macrocode} +% +% % \subsection{Tiles}\label{tiles} % % Tesselations are a type of fill in which a rectangular pattern is @@ -3478,6 +3734,8 @@ enddef; % \end{macrocode} % +% +% % \section{Bounding Boxes of Paths}\label{bboxes} % % To fill a region with other than a solid fill, we normally fill a @@ -3522,6 +3780,9 @@ enddef; % This description applies only to \MF, because \MP{} has built-in % facilities for determining the bounding box. % +% I have changed \gbc{ctrlsbbox} to have the same syntax as \gbc{getbbox}. +% I don't know why I defined it differently. +% % \RoutineIndex{pnt} % \RoutineIndex{pre} % \RoutineIndex{post} @@ -3532,6 +3793,7 @@ vardef pnt@# (expr p) = point @# of p enddef; vardef pre@# (expr p) = precontrol @# of p enddef; vardef post@# (expr p) = postcontrol @# of p enddef; +numeric bbox_split; bbox_split := 4; def getbbox (suffix ll, ur) expr g = % ll := llcorner g; ur := urcorner g; %<*MF> @@ -3541,20 +3803,44 @@ def getbbox (suffix ll, ur) expr g = ll := pairmin (ll, pnt[_j] (g)); ur := pairmax (ur, pnt[_j] (g)); endfor for _j = 1 upto _s*(length g): - ctrlsbbox (subpath ((_j-1)/_s, _j/_s) of g) (ll, ur); + ctrlsbbox (ll, ur) subpath ((_j-1)/_s, _j/_s) of g; endfor % if showbbox: noclip ( safedraw rect (ll, ur) ); fi enddef; %<*MF> -numeric bbox_split; bbox_split := 2; -def ctrlsbbox (expr p) (suffix ll, ur) = +def ctrlsbbox (suffix ll, ur) expr p = ll := pairmin ( pairmin (ll, post0 (p)), pre 1 (p) ); ur := pairmax ( pairmax (ur, post0 (p)), pre 1 (p) ); enddef; % +% \end{macrocode} +% +% \DescribeRoutine{getradius} +% This is very similar to \gbc{getbbox}, but gets a ``bounding circle'' +% instead of a box. It is used to get nearly the smallest circle with a +% given center that contains a path. The path is shifted to place the +% center at the origin and then this function is called. Similarly, +% \DescribeRoutine{ctrlsradius} +% \gbc{ctrlsradius} is used like \gbc{ctrlsbbox}. +% \begin{macrocode} +def getradius (suffix rad) expr g = + setsplit (_s) bbox_split; + rad := abs (pnt0 (g)); + for _j = 1 upto length g: + rad := emax(rad, abs(pnt[_j] (g))); + endfor + for _j = 1 upto _s*(length g): + ctrlsradius (rad) subpath ((_j-1)/_s, _j/_s) of g; + endfor +enddef; + +def ctrlsradius (suffix rad) expr p = + rad := emax( emax (rad, abs(post0 (p))), abs(pre1 (p) )) +enddef; + % \end{macrocode} % % We also have \gbc{tightbbox} and \gbc{tbbox} in \MF{} but these are no @@ -3568,11 +3854,9 @@ enddef; % \mfc{.5} (accurate enough, assuming pixel units). This is only called by % \gbc{tbbox}, which is never used. % -% \DescribeRoutine{_xlimit} % \gbc{xlimit(x)} returns a value of true if the path \gbc{g} doesn't -% cross the vertical line at \gbc{x}. -% \DescribeRoutine{_ylimit} -% \gbc{ylimit(y)} is the same for the horizontal line at \gbc{y}. +% cross the vertical line at \gbc{x}. \gbc{ylimit(y)} is the same for the +% horizontal line at \gbc{y}. % \begin{macrocode} %<*unused> def tightbbox (expr g) (suffix ll, ur) = @@ -3618,6 +3902,8 @@ enddef; % % \end{macrocode} % +% +% % \section{Device Coordinate Rendering Commands}\label{basicrendering} % % We use the word `rendering' to refer to commands that accept a path @@ -3625,6 +3911,7 @@ enddef; % All the commands in this section expect paths, pairs and dimensions in % device coordinates. % +% % \subsection{Drawing}\label{basicdrawing} % % \DescribeRoutine{safedraw} @@ -3654,6 +3941,7 @@ enddef; % \end{macrocode} % +% % \subsection{Filling}\label{basicfilling} % % \DescribeRoutine{NoCycle} @@ -3712,6 +4000,7 @@ enddef; % \end{macrocode} % +% % \subsection{Clipping}\label{clipping} % % \DescribeRoutine{safeclip} @@ -3727,6 +4016,8 @@ enddef; % \end{macrocode} % +% +% % \section{Graph Coordinate Rendering}\label{rendering} % % \DescribeRoutine{store} @@ -3764,6 +4055,7 @@ vardef stored (suffix fs) expr f = store (fs) f; f enddef; % \end{macrocode} % +% % \subsection{Drawing}\label{drawing} % % \DescribeRoutine{drawn} @@ -3797,18 +4089,23 @@ enddef; % % The reason for using a loop (at the end) that draws the \gbc{sinewave} % path in pieces, is that all the turning can quickly exceed \MF{}'s limit -% on the autorounding stack. I'd never heard of this stack until I ran +% on the ``rounding table size''. I'd never heard of this until I ran % this without a loop and received the ``capacity exceeded'' message. This % turns out to be a problem mostly when the ratio of \gbc{len} to % \gbc{wid} is too small and the `humps' of the sine are more like % `bulbs'. However it is always a problem with \gbc{corkscrew} (below). +% +% There is no need for the loop in \MP{}, nor in \MF{} if +% \mfc{autorounding} is set to $0$, but \mfpic's curved paths definitely +% look better with the default \mfc{autorounding=2}. % \begin{macrocode} def zigzag = colorzigzag (drawcolor) enddef; def colorzigzag (expr clr) = colorwiggle (false, clr, 0) enddef; def sinewave = colorsinewave (drawcolor) enddef; def colorsinewave = colorwiggle (true) enddef; -vardef colorwiggle (expr smth, clr, tens, blen, elen, len, wid) expr f = +vardef colorwiggle (expr smth, clr, tens, blen, elen, len, wid) expr f += convertpath (g) f; setuplengtharray (cumlen, totlen, ct) g; save B; @@ -3919,6 +4216,7 @@ enddef; % \end{macrocode} % +% % \subsection{Filling, unfilling and clipping}\label{filling} % % \DescribeRoutine{filled} @@ -3943,6 +4241,7 @@ vardef Clip expr c = safeclip zconv (c); c enddef; % \end{macrocode} % +% % \subsection{Shading}\label{shading} % % \DescribeRoutine{shade} @@ -4117,6 +4416,7 @@ enddef; % \end{macrocode} % +% % \subsection{Hatching}\label{hatching} % % \DescribeRoutine{thatch} @@ -4183,6 +4483,88 @@ enddef; % \end{macrocode} % +% +% \subsection{Gradients} +% +% \DescribeRoutine{axialgradient} +% We pass a \mfc{vardef}-ed function that is to provide the range of +% colors. It can output colors of different types if desired. Two +% natural methods are: (1)~interpolate between colors of the same type:\\ +% \indent\mfc{vardef clrgrad (expr t) = (t)[red,blue] enddef}\\ +% and (2)~extract colors from a previously built array of colors:\\ +% \indent\mfc{vardef clrgrad (expr t)= A[round(t*N)]}\\ +% where, \mfc{A0}, \mfc{A1},\dots \mfc{A[N]} are colors (necessarily of +% the same type). +% +% Since we simply fill strips with a single color, \gbc{sp} is the +% thickness of the strip (in device units) and \gbc{theta} is the angle +% by which these strips differ from being horizontal. +% \begin{macrocode} +vardef axialgradient (suffix clr) (expr sp, theta) expr f = + convertpath (g) f; + if not cycle g: NoCycle("axialgradient") g; + else: + newpicture (_grd); + setbbox (ll, ur) g rotated -theta; + axialgradientf (clr, _grd) (theta, sp, ll, ur); + DoClip (_grd); clipto (_grd) (g); +% safeunfill g; + _orto (active_plane, _grd); + fi + f +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{areagradient} +% This fills a cyclic path with colored pixels, with the color +% determined by the \mfc{vardef}-ed function \gbc{clr} which takes two +% parameters. The size of the pixels is given in the last two parameters +% \gbc{sp} and \gbc{tp} which are specified in device units. +% \begin{macrocode} +vardef areagradient (suffix clr) (expr sp, tp) expr f = + convertpath (g) f; + if not cycle g: NoCycle("areagradient") g; + else: + newpicture (_agr); + setbbox (ll, ur) g; + areagradientf (clr, _agr) (sp, tp, ll, ur); + DoClip (_agr); clipto (_agr) (g); +% safeunfill g; + _orto (active_plane, _agr); + fi + f +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{radialgradient}\label{getrad} +% This fills a cyclic path with colored circular strips, with the color +% determined by the \mfc{vardef}-ed function \gbc{clr} which takes one +% parameters. The thickness of the strips is given in the last parameter +% \gbc{sp} which are specified in device units. The command +% \gbc{getradius} finds the distance from the center to the farthest point +% of \gbc{f}. It was added (see section~\ref{bboxes}) solely for this use. +% \begin{macrocode} +vardef radialgradient (suffix clr) (expr sp, ctr) expr f = + convertpath (g) f; + if not cycle g: NoCycle("radialgradient") g; + else: + setpair (_ctr) zconv (ctr); + newpicture (_agr); + save _rad; + getradius (_rad) g shifted - _ctr; + radialgradientf (clr, _agr) (sp, _ctr, _rad); + DoClip (_agr); clipto (_agr) (g); +% safeunfill g; + _orto (active_plane, _agr); + fi + f +enddef; + +% \end{macrocode} +% +% % \subsection{Tesselations}\label{tess} % % \DescribeRoutine{tess} @@ -4215,6 +4597,7 @@ enddef; % \end{macrocode} % +% % \subsection{Dots and dashes}\label{dashes} % % \MP{} already has commands for drawing a dashed or dotted curve, @@ -4470,8 +4853,8 @@ vardef makelengtharray (suffix clen) suffix p = numeric clen[]; clen := _s * length p; clen0 := 0; for _i = 1 upto clen: - clen[_i] := clen[_i-1] + abs (pnt[_i/_s] (p) - pnt[(_i-1)/_s] (p)) / - _rescale_factor; + clen[_i] := clen[_i-1] + abs (pnt[_i/_s] (p) - pnt[(_i-1)/_s] (p)) + / _rescale_factor; endfor clen[clen] enddef; @@ -4725,6 +5108,7 @@ enddef; % \end{macrocode} % +% % \subsection{Double-line drawing}\label{doubleline} % % \DescribeRoutine{doubledraw} @@ -4743,6 +5127,8 @@ enddef; % \end{macrocode} % +% +% % \section{Points Symbols and Other Pictures}\label{symbols} % % \DescribeRoutine{centerit} @@ -4914,6 +5300,8 @@ enddef; % \end{macrocode} % +% +% % \section{Axes, Tic Marks, and Grids}\label{axes} % % \DescribeRoutine{arrowdraw} @@ -5482,6 +5870,8 @@ enddef; % \end{macrocode} % +% +% % \section{Path Construction}\label{pathconstruction} % % This section is devoted to commands that accept a list or array of @@ -5490,6 +5880,7 @@ enddef; % points, lines and circles associated with a triangle. No \mfpic{} % interface is yet available for the triangle commands. % +% % \subsection{Piecewise linear paths}\label{linear} % % \DescribeRoutine{rect} @@ -5658,7 +6049,9 @@ enddef; % \DescribeRoutine{mkpoly} % This produces the path of line segments connecting \gbc{pts1}, % \gbc{pts2}, etc., closing it up if the boolean \gbc{cyclic} is true. -% It is also used with an array of paths instead of points. +% It can also be used with an array of paths instead of points, connecting +% the end of each with the beginning of the next. We do this in \mfpic{}'s +% \cs{connect} \dots\ \cs{endconnect} construct. % \begin{macrocode} vardef mkpoly (expr cyclic) (suffix pts) = for _i = 1 upto pts-1: pts[_i]-- endfor @@ -5672,8 +6065,9 @@ enddef; % list of pair expressions, forms an array from them and calls % \gbc{mkpoly}. % \DescribeRoutine{NoPoints} -% \mfc{NoPoints} prints a warning and sets the array to a single point, -% the origin. +% \mfc{NoPoints} is called when an array of points is defined (using +% setpairs) that returns $0$ for the number of pairs. It prints a warning +% and sets the array to a single point, the origin. % \begin{macrocode} vardef polyline (expr cyclic) (text t) = setpairs (_pl) (t); @@ -5718,10 +6112,32 @@ enddef; % I needed the following to illustrate Brownian motion. It takes a given % starting point, a given number of steps and a scaling factor. It % generates a sequence of random points, each one being chosen randomly -% using a Gaussian distribution centered at the previous point. Strictly +% using a Gaussian distribution centered at the previous point. The +% standard deviation of the random distance is the scale factor. Strictly % speaking this is a Gaussian random walk, not Brownian motion. A true % Brownian motion would be a limit of these, with \gbc{num} tending to % $\infty$ and \gbc{sc} tending to 0. +% +% \DescribeRoutine{randomwalk} +% This is like \gbc{brownianpath}, but the distance from one point to +% the next is always the same, only the direction is random. It takes +% the same arguments as \gbc{brownianpath} +% +% \DescribeRoutine{browniangraph} +% This command takes a given number of steps \gbc{num} and a scaling +% factor/step size \gbc{scst}. It generates a sequence of points, each one +% being chosen right of the previous one by the step size \gbc{scst} and +% randomly up or down using a Gaussian distribution centered at the +% previous $y-value$. The Gaussian distribution has standard deviation +% equal to \gbc{scst}. The path starts at $(0,0)$. One needs to transform +% the path to get a different start or a scale factor different from the +% step size. +% +% In \MF{} we run into capacity problems when \gbc{num} is greater than +% 500 or so. This is the \mfc{autorounding} problem again (see the +% discussion at \gbc{sinewave}. We can't use the same technique we used +% there since it is the drawing that invokes \mfc{autorounding} and these +% macros only construct paths; they don't draw them. % \begin{macrocode} vardef brownianpath (expr start, num, sc) = setnumeric (_brp) 1; @@ -5733,9 +6149,29 @@ vardef brownianpath (expr start, num, sc) = endfor mkpoly (false, _brp) enddef; +vardef randomwalk (expr start, num, dst) = + setnumeric (_rdw) 1; + setpair (_tmp) start; + pair _rdw[]; _rdw1 := _tmp; + for _idx := 1 upto num: + _tmp := _tmp + dst*dir(uniformdeviate(360)); + _rdw[incr _rdw] := _tmp; + endfor + mkpoly (false, _rdw) +enddef; +vardef browniangraph (expr num, scst) = + setnumeric (_brg) 1; + pair _tmp, _brg[]; _tmp := _brg1 := (0,0); + for _idx := 1 upto num: + _tmp := _tmp + scst*(1,normaldeviate); + _brg[incr _brg] := _tmp; + endfor + mkpoly (false, _brg) +enddef; % \end{macrocode} % +% % \subsection{Smooth paths}\label{smooth} % % We added an optional parameter for the tension of smooth curves to @@ -5839,8 +6275,8 @@ vardef mkconvex (expr tens, cyclic) (suffix pts) = _B[_j] := sqrt(abs((pts[_j]-pts[_j-1])xprod(pts[_j+1]-pts[_j]))); endfor if cyclic: - _B1 := sqrt(abs((pts1 - pts[pts])xprod(pts2 - pts1))); - _B[pts] := sqrt(abs((pts[pts]-pts[pts-1])xprod(pts1 - pts[pts]))); + _B1 := sqrt(abs((pts1 - pts[pts])xprod(pts2 - pts1))); + _B[pts] := sqrt(abs((pts[pts]-pts[pts-1])xprod(pts1 - pts[pts]))); else: _B1 := _B2; _B[pts] := _B[pts-1]; @@ -5903,12 +6339,16 @@ enddef; numeric default_tension; default_tension := 1; def curve = tcurve (default_tension) enddef; vardef tcurve (expr tens, cyclic) (text t) = - setpairs (_tc) (t); mksmooth (tens, cyclic, _tc) + setpairs (_tc) (t); + if _tc=0: NoPoints("curve", _tc); fi + mksmooth (tens, cyclic, _tc) enddef; def ccurve = tccurve (default_tension) enddef; vardef tccurve (expr tens, cyclic) (text t) = - setuniquepairs (_tcc) (t); mkconvex (tens, cyclic, _tcc) + setuniquepairs (_tcc) (t); + if _tcc=0: NoPoints("ccurve", _tcc); fi + mkconvex (tens, cyclic, _tcc) enddef; % \end{macrocode} @@ -5978,8 +6418,8 @@ vardef mkqbezier (expr cyclic) (suffix pts) = if pts=1: {0,0} else: for _i = 2 step 2 until pts - 1: - ..controls 1/3[pts[_i], pts[_i-1] ] and 1/3[pts[_i], pts[_i+1] ].. - pts[_i+1] + ..controls 1/3[pts[_i], pts[_i-1]] + and 1/3[pts[_i], pts[_i+1]].. pts[_i+1] endfor if cyclic: ..controls 1/3[ pts[pts], pts[pts - 1] ] @@ -6114,12 +6554,14 @@ def tfcncurve = functioncurve enddef; vardef functioncurve (expr ftens) (text t) = settension (_ftens) ftens; if _ftens < 1/3: _ftens := 1/3; fi setuniquepairs (_fc) (t); + if _fc=0: NoPoints ("functioncurve", _fc); fi if _fc > 1: _fc0 := _fc1; _fc[_fc+1] := _fc[_fc]; fi mkfcnpath (_ftens) (_fc) enddef; % \end{macrocode} % +% % \subsection{Splines with explicit controls}\label{splines} % % For these quadratic B-splines, a list of pairs representing the control @@ -6240,6 +6682,7 @@ enddef; % \end{macrocode} % +% % \subsection{Splines with computed controls}\label{computedsplines} % % A cubic spline through a set of points is a curve obtained by joining @@ -6352,9 +6795,9 @@ enddef; % than pair values. Such are often used to interpolate functions. That is, % given pairs $(x\sb j,y\sb{j})$, and assuming they lie on the graph of % some function (generally unknown), fill in the graph with $y = f(x)$ -% where $f$ is a cubic function of $x$ in each interval $x\sb j < x < x\sb -% {j+1}$, making sure that the resulting graph is as smooth as possible at -% the points $x\sb j$. +% where $f$ is a cubic function of $x$ in each interval $x\sb j \le x +% \le x\sb {j+1}$, making sure that the resulting graph is as smooth as +% possible at the points $(x\sb j, y\sb j)$. % % The requirements on our $2$-dimensional path are the following: % \begin{enumerate} @@ -6481,6 +6924,7 @@ enddef; % \end{macrocode} % +% % \subsection{Arcs, circles and ellipses}\label{arcs} % % We have multiple commands that generate circular arcs, differing in @@ -6502,7 +6946,9 @@ enddef; % % There is really no problem with \gbc{mkarc} itself: if you can express % both \gbc{center} and \gbc{begpt} in \MF, then the other values on the -% arc should be no problem. +% arc should normally be no problem. (Of course, if the radius is near +% \mfc{infinity}, there could be points on the arc with coordinates near +% \mfc{2infinity}, causing overflow in \MF{}. One hopes this is rare.) % % Care has been taken that changing the sign of various parameters % produces reasonable results. And there should be no more problem for @@ -6527,7 +6973,7 @@ enddef; % is mainly to ensure that the arc begins at \gbc{begpt} and ends at % \gbc{endpt} (exactly). A \gbc{sweep} of $0$ is actually incompatible % with any case where \gbc{begpt<>endpt} unless \gbc{center} is -% literally at infinity, but we allow it even though I am pretty sure +% literally at $\infty$, but we allow it even though I am pretty sure % the other arc commands all filter out that case. % \begin{macrocode} vardef mkarc (expr center, begpt, endpt, sweep) = @@ -6546,7 +6992,7 @@ enddef; % % \DescribeRoutine{arc} % The most basic: center of circle, starting point of arc, and angle -% subtended. Another name for \gbc{arc} is \gbc{arccps}, (\gbc{cps} is +% subtended. Another name for \gbc{arc} is \gbc{arccps}, (``\gbc{cps}'' is % for ``center, point, sweep''). % \begin{macrocode} vardef arc (expr center, begpt, sweep) = @@ -6573,7 +7019,7 @@ def arccps = arc enddef; % used them and the several cases that they had to consider are reduced % because the \mfc{if} in this command takes care of some of them. % -% The code for finding \gbc{m} uses the fact that chord and the line +% The code for finding \gbc{m} uses the fact that the chord and the line % from one of its endpoints to the midpoint subtend a circular arc of % \gbc{sweep/2} and so the angle between them is half that, \gbc{sweep/4}. % The code gets the intersection between the line in that direction and @@ -6589,7 +7035,7 @@ def arccps = arc enddef; % circle. This gives the radius mentioned above. % \begin{macrocode} vardef arcpps (expr begpt, endpt, sweep) = - if begpt = endpt: begpt--endpt + if (begpt = endpt) or (sweep = 0): begpt--endpt else: setpair (cd) unitvector (endpt-begpt); if abs(sweep) <= 45: @@ -6761,20 +7207,92 @@ vardef circlepps (expr one, two, sweep) = enddef; vardef circlepp (expr small, one, two, rad) = - arcpp (small, one, two, rad) & arcpp (not small, two, one, rad) & cycle + arcpp (small, one, two, rad) & arcpp (not small, two, one, rad) + & cycle enddef; def circleppr (expr one, two, rad, small) = circleppr (one, two, rad, small) enddef; +% \end{macrocode} +% +% Now we implement a different way to specify an ellipse, essentially +% specifying it by a parallelogram in which it is to be inscribed. +% +% \DescribeRoutine{quarterellipse} +% If an ellipse is inscribed in a parallelogram, tangent to all four +% sides at the midpoints, this command produces one ``corner'' of that +% ellipse. The arguments \mfc{A} and \mfc{C} are the midpoints of two +% adjacent sides and \mfc{B} is the corner between those two sides. This +% quarter-ellipse starts at \mfc{A} in the direction \mfc{B-A} and ends at +% \mfc{C} in the direction \mfc{C-B}. As a path \mfc{p} it has two segments, where +% \mfc{point 0 of p} is \mfc{A}, \mfc{point 2 of p} is \mfc{C}, while +% \mfc{point 1 of p} lies on the diagonal of the parallelogram through +% \mfc{B} and has direction there the same as \mfc{C-A}. +% +% This was created for the purpose of rounding off corners of a polygonal +% path. +% \begin{macrocode} +vardef quarterellipse(expr A,B,C) = + save T_; + transform T_; + (1,0) transformed T_ = A; + (1,1) transformed T_ = B; + (0,1) transformed T_ = C; + quartercircle scaled 2 transformed T_ +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{halfellipse} +% While \gbc{quarterellipse} is for corners, I don't have much use for +% \gbc{halfellipse}. Nevertheless, it seems wise (and easy) to provide a +% definition. +% +% The pairs \mfc{A}, \mfc{B}, and \mfc{C} are three midpoints of a +% parallelogram with \mfc{A} and \mfc{C} on opposite sides and \mfc{B} on +% a third side. This determines a unique parallelogram, and +% \gbc{halfellipse} starts at \mfc{A}, passing through \mfc{B} then +% \mfc{C}, tangent to the respective sides. It makes a point of building +% it out of two \gbc{quarterellipse}\,s as \mfc{halfcircle} does with +% \mfc{quartercircle} (at least in \MF{}). We just have to compute their +% corners. +% \begin{macrocode} +vardef halfellipse (expr A,B,C) = + save P_; pair P_; + P_ = (C - A)/2; + quarterellipse (A, B - P_, B) & quarterellipse (B, B + P_, C) +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{fullellipse} +% For \gbc{fullellipse} we specify the center \mfc{C} of the parallelogram +% and the midpoints \mfc{A} and \mfc{B} of two adjacent sides. We compute +% the midpoints of the other two sides and draw two \gbc{halfellipse}\,s. +% +% Note that the points \gbc{A} and \gbc{B} do not correspond to the +% usual radii of an ellipse unless the corresponding parallelogram is +% actually a rectangle (i.e., only if $\angle ACB$ is a right angle). +% \begin{macrocode} +vardef fullellipse (expr C, A, B) = + save P_; pair P_; + P_ := 2[A,C]; + halfellipse (A,B,P_) & halfellipse (P_,2[B,C],A) & cycle +enddef; + % \end{macrocode} % % \DescribeRoutine{pathcenter} % This finds the center of a circle. For other paths, the point found % may be meaningless (but it will also obtain the center of an arc or a -% rectangle). It takes three supposedly distinct points on the path and -% finds the intersection of the perpendicular bisectors of two chords. +% rectangle). It takes three or four supposedly distinct points on the +% path and finds the intersection of the perpendicular bisectors of two +% chords. +% +% This code is rather non-robust if applied to an arc that has angular +% measure very close to either 0 or 360. % \begin{macrocode} vardef pathcenter expr p = save a, cntr, n; pair cntr, a[]; @@ -6782,7 +7300,7 @@ vardef pathcenter expr p = a1 = pnt 0 (p); a3 = pnt [n/2] (p); if cycle p: - a2 = pnt [n/4] (p); + a2 = pnt [ n/4] (p); a4 = pnt [3n/4] (p); else: a2 := a3; @@ -6804,8 +7322,8 @@ enddef; % This is just the circle through the three corners. % % \DescribeRoutine{incircle} -% The command \gbc{incircle} produces the circle inside the triangle that -% is tangent to all three sides. It makes use of the fact that the two +% The command \gbc{incircle} produces the circle that is tangent to all +% three sides of the triangle. It makes use of the fact that the two % tangent points on the sides adjacent to corner \gbc{A} (for example) are % equidistant from \gbc{A}. The three equations then express the fact that % the sum of the two distances from the tangent point to the corners on @@ -6859,12 +7377,26 @@ enddef; % \end{macrocode} % % \DescribeRoutine{pshcircle} -% Here is a couple of circles maybe only I need. They are the +% Here are a couple of circles maybe only I need. They are the % pseudohyperbolic circles in the unit disk and upper half-plane. % One supplies a point that must be inside the unit circle or above % the $x$-axis, and a radius that must be less than $1$. Some degenerate % cases will not generate an error. We code this with a boolean that % determines whether the disk or the half-plane is to be assumed. +% +% If $\alpha=(a,b)$ is the hyperbolic center (the \mfc{ctr} parameter) +% and $\rho$ is the pseudohyperbolic radius (the \mfc{rad parameter}), +% the formula for the (Euclidean) center $C$ and radius $R$ of the circle +% is, for the unit disk: +% $$ +% C = \frac{ (1 - \rho^2)a }{1 - \rho^2|a|^2},\quad +% R = \frac{\rho(1 - |a|^2)}{1 - \rho^2|a|^2} +% $$ +% and for the half-plane: +% $$ +% C = a + \frac{(1 + \rho^2}{1 - \rho^2}b,\quad +% R = \frac{2\rho b}{1 - \rho^2} +% $$ % \begin{macrocode} vardef pshcircle (expr disk, ctr, rad) = if disk: @@ -6877,49 +7409,176 @@ vardef pshcircle (expr disk, ctr, rad) = elseif abs(ctr) >= 1 : if abs(ctr) > 1: GBerrmsg ("Impossible center of pseudohyperbolic circle.") - "The center of a pseudohyperbolic circle must be in " + "The center of this pseudohyperbolic circle must be in " & "the unit disk."; fi onepointpath (true,ctr) else: - % compute Euclidean center and radius (and a denominator used twice - % in calculations). save _r, _dnm; _r := abs(ctr); _dnm := 1 - _r*_r*rad*rad; - circle ( (1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm) + circle ((1 - rad*rad)/_dnm*ctr, rad*(1 - _r*_r)/_dnm) fi else: if rad >= 1 : - GBerrmsg ("Impossible pseudohyperbolic circle.") + GBerrmsg ("Impossible radius of pseudohyperbolic circle.") "The radius of a pseudohyperbolic circle must be less than 1."; onepointpath (true,ctr) elseif ypart ctr <= 0: if ypart ctr < 0: - GBerrmsg ("Impossible pseudohyperbolic circle.") - "The center of a pseudohyperbolic circle must be in " + GBerrmsg ("Impossible center of pseudohyperbolic circle.") + "The center of this pseudohyperbolic circle must be in " & "the upper half-plane."; fi onepointpath (true,ctr) else: - % compute Euclidean center and radius (and a denominator used twice - % in calculations). - % Euclidean center at xpart ctr + (1 + R^2)/(1 - R^2)*ypart ctr - % Euclidean radius 4R/(1 - R^2)*ypart ctr save _y, _dnm; _y := ypart ctr; _dnm := 1 - rad*rad; - circle ( (xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y) + circle ((xpart ctr, (1 + rad*rad)/_dnm * _y), 2rad/_dnm*_y) + fi + fi +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{UHPgeodesic} +% Here is another arc-producing command. What it produces is the +% hyperbolic geodesic from one point to another in the \emph{upper +% half-plane} (UHP). While, theoretically, the points should both be in +% the UHP, where the hyperbolic geometry is defined, the computations make +% sense for any pair of points. This could be useful, so I do not enforce +% this theoretical requirement. +% +% Unless two points have the same xpart, there is a unique circle passing +% through them that meets the $x$-axis at a right angle. The hyperbolic +% geodesic is an arc of that circle. The path starts at the first listed +% point and ends at the second. Of the two possible arcs that connect +% these points, it is the one that doesn't cross the $x$-axis (if there +% is one). Our computations simply determine the angle of the arc and call +% \gbc{arcpps}. +% +% When the points have the same xpart, the hyperbolic geodesic is the +% line segment connecting them. When the points have yparts with opposite +% signs, both arcs cross the $x$-axis. Our code produces the shorter one. +% If both are $180$ degrees, the one that lies all on the same side of the +% vertical line through $A$ is produced ($A$ being the first argument). +% +% Our method is based on the fact that the reflection $C$ of $A$ (to the +% other side of the $x$-axis) lies on the circle on which the arc lies. +% The angle between $A$ and $B$ when viewed from this point is therefore +% half the angle of the arc. We actually reflect the point farthest from +% the $x$-axis, as this produces better results. +% +% If $A$ and $B$ are on opposite sides of the $x$-axis, then $C$ might +% coincide with one of the points. In this case $A$ and $B$ would +% necessarily have equal xparts, a case we will already have processed. +% +% If both points lie on the $x$-axis, the computations produce the +% semicircle from the first to the second in the upper half-plane. +% \begin{macrocode} +vardef UHPgeodesic (expr A, B) = + if xpart A = xpart B: + A--B + else: + save ang_, C_; pair C_; + if abs(ypart A) < abs(ypart B): + C_ := conj B; + else: + C_ := conj A; + fi + if ypart C_ = 0: % both on x-axis + ang_ := anglefromto(up, B - A); + else: + ang_ := anglefromto(A - C_, B - C_); fi + arcpps(A, B, 2ang_) + fi +enddef; + +% \end{macrocode} +% +% \DescribeRoutine{UDgeodesic} +% There is a hyperbolic geometry defined for any simply connected open +% set. The standard examples of such are the UHP and the unit disk (UD). +% This next macro produces the geodesic in the UD. Once again it is the +% arc of a circle and, if the two points do not lie on the same diameter, +% that circle is the unique one through the two points that meets the +% boundary of $UD$ at a right angle. When the two points do lie on the +% same then the geodesic is the straight line connecting the points. +% +% The method we use is also based on reflection, where the `reflection' of +% a point $A$ is given by $C = A/|A|^2$. Computing this can cause overflow +% if $|A|$ too near $0$. Unfortunately, overflow can also occur if either +% point lies are outside the UD. That is because, even for modest sizes of +% $A$ and $B$, the part of the mentioned circle that lies outside the UD +% can approach \gbc{infinity} in size, making the arc itself impossible to +% draw. While it is feasible to compute when this will occur, we try to +% keep it simple by using an approach that is only guaranteed to work when +% the points lie in the unit disk. A minor modification allows it to to +% always work when only one of the points is outside. This is because the +% geodesic is not unique and we can easily choose one that doesn't +% overflow. +% +% We isolate several special cases: if either point is the origin or if +% the points have the same angle, a straight line is produced. If either +% point is on the boundary, the computation is based on the fact that the +% arc is tangent to the direction of that point. In the remaining cases, +% we compute two angles based on reflecting both points. In the case where +% both points lie inside or both lie outside, these angles are +% theoretically equal, but when one point lies inside and the other +% outside, these angles have opposite signs and their absolute values sum +% to 360. They correspond to going opposite ways around the circle. We +% choose the shorter arc as being more ``geodesic-like''. +% +% If $C$ is the point being reflected, but it is close enough to the +% origin to make overflow a significant problem, we rescale the triangle +% used to find the angle: we compute the angle between $|C|A$ and $|C|B$ +% as viewed from $C/|C|$. +% \begin{macrocode} +vardef UDgeodesic (expr A, B) = + save a_, b_; + a_ := abs(A); b_ = abs(B); + if (a_ = 0) or (b_ = 0): + A--B + elseif angle A = angle B: + A--B + else: % note: A, B and B-A are all nonzero from this point + save ang_; + if a_ = 1: + ang_ := anglefromto (if b_>1: A else: -A fi, B-A) + elseif b_ = 1: + ang_ := anglefromto (A-B, if a_>1: B else: -B fi) + else: + save C_; pair C_; + % reflecting A + if a_ < eps: + C_ := unitvector A; + ang_1 := anglefromto(a_*A - C_, a_*B - C_); + else: + C_ := (1/a_)*unitvector A; + ang_1 := anglefromto(A - C_, B - C_); + fi + % reflecting B + if b_ < eps: + C_ := unitvector B; + ang_2 := anglefromto(b_*A - C_, b_*B - C_); + else: + C_ := (1/b_)*unitvector B; + ang_2 := anglefromto(A - C_, B - C_); + fi + ang_ := if abs(ang_1) < abs(ang_2): ang_1 else: ang_2 fi; + fi + arcpps(A, B, 2ang_) fi enddef; % \end{macrocode} % % \DescribeRoutine{barycenter} -% This is the average of the three corners of the triangle, or of any -% path. If \gbc{t} is an open path with length $n$ and the nodes are -% $x\sb0$ through $x\sb n$, the barycenter is +% This is the average of the three corners of the triangle, or of all the +% nodes of any path. If \gbc{t} is an open path with length $n$ and the +% nodes are $x\sb0$ through $x\sb n$, the barycenter is % $$ \frac{1}{n+1}\sum\sb{j=0}\sp{n} x\sb j. $$ % If \gbc{t} is a cycle with $x\sb n = x\sb0$, then it is % $$ \frac{1}{n}\sum\sb{j=0}\sp{n-1} x\sb j. $$ @@ -6952,6 +7611,39 @@ enddef; % \end{macrocode} % +% \DescribeRoutine{mkbrace} +% Because it doesn't really fit anywhere else, and because it is not +% really enough to waste a whole subsection on, we put \gbc{mkbrace} here. +% It is a command to draw a brace (i.e., a ``$\lbrace$'' shape) with its +% ends and its cusp at given points. The start is at \gbc{S}, the end at +% \gbc{E} and the cusp at \gbc{C}. \gbc{C} should be close to, but not +% on, the line from \gbc{S} to \gbc{E}. It should also not be too close to +% \gbc{S} or \gbc{E}, as we need room to draw two quarter circles on +% either side of \gbc{C} and one at each of \gbc{S} and \gbc{E}. +% \begin{macrocode} +vardef mkbrace (expr S, C, E) = + save R_, U_, V_, Z_; + pair U_, V_, Z_[]; + U_ := unitvector (E-S); + V_ := U_ rotated 90; + + R_ := 0.5*(C-S) dotprod V_; + if R_ = 0: + S--C + else: + if R_ < 0 : V_ := -V_; R_ := -R_; fi + V_ := R_*V_; U_ := R_*U_; + Z_1 := S + V_ + U_; + Z_2 := C - V_ - U_; + Z_3 := C - V_ + U_; + Z_4 := E + V_ - U_; + S{V_}..{U_}Z_1--Z_2{U_}..{V_}C{-V_}..{U_}Z_3--Z_4{U_}..{-V_}E + fi +enddef; + +% \end{macrocode} +% +% % \subsection{Plotting of functions}\label{functionplots} % % In these macros, if the boolean argument \gbc{sm} is true then the @@ -7148,7 +7840,7 @@ tolerancefactor := .02; vardef mklevelset (expr sm, tens, X, Y, t, a, b, c, d) = save _inside_; vardef _inside_ (expr U, V) = - inside_levelset (U, V) and between (a, b) (U) and between (c, d) (V) + inside_levelset(U, V) and between(a, b)(U) and between(c, d)(V) enddef; if not _inside_ (X, Y): GBwarn "Invalid seed point for levelset."; @@ -7273,16 +7965,16 @@ vardef tRKIV (expr sm, tens, zstart, ds, N) (text _RHS_) = for _idx := 2 upto _trj: _dt := ds/emax(1,abs(_RHS_(_tt,_ztr))); _th := _tt + .5_dt; - _dz1 := _dt*_RHS_(_tt, _ztr); % displacement based on current point + _dz1 := _dt*_RHS_(_tt, _ztr); % displacement for current point _ztmp := _ztr + .5_dz1; % 1st midpoint % use _th instead of twice calculating (_tt + .5_dt) - _dz2 := _dt*_RHS_(_th, _ztmp); % displacement based on 1st midpoint + _dz2 := _dt*_RHS_(_th, _ztmp); % displacement for 1st midpoint _ztmp := _ztr + .5_dz2; % 2nd midpoint - _dz3 := _dt*_RHS_(_th, _ztmp); % displacement based on 2nd midpoint + _dz3 := _dt*_RHS_(_th, _ztmp); % displacement for 2nd midpoint _ztmp := _ztr + _dz3; % temporary end point - % get time for next loop now since we need it right away in next line: + % get time for next loop now since we need it in the next line: _tt := _tt + _dt; - _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement based on end point + _dz4 := _dt*_RHS_(_tt, _ztmp); % displacement for end point % get next point _ztr := _ztr + (_dz1 + 2_dz2 + 2_dz3 + _dz4)/6; _trj[_idx] := _ztr; @@ -7308,8 +8000,11 @@ enddef; % \end{macrocode} % +% +% % \section{Modification of Paths}\label{modification} % +% % \subsection{Closing a path}\label{closing} % % In \MF{} one closes a path with any legal path connection between the @@ -7477,7 +8172,8 @@ vardef makesector expr p = (pathcenter p)--p--cycle enddef; % The \gbc{setpairs} statement makes \gbc{pp1}, \gbc{pp2} and \gbc{pp3} % three points on the arc \gbc{p} in order. The arc we want goes from % \gbc{pp3} to \gbc{pp1} with angle twice that of the corner angle at -% \gbc{pp2}. +% \gbc{pp2}. This function can be applied to an arbitrary path, and its +% result will be an arc, but not necessarily a meaningful one. % \begin{macrocode} vardef arccomplement expr p = if cycle p: onepointpath (false, pnt0(p)) @@ -7490,6 +8186,7 @@ enddef; % \end{macrocode} % +% % \subsection{Trimming a path}\label{trimming} % % \DescribeRoutine{cutoffbefore} @@ -7545,6 +8242,7 @@ enddef; % \end{macrocode} % +% % \subsection{Creating arrows}\label{arrows} % % First, some better \mfc{direction} commands. They makes use of the fact @@ -7555,7 +8253,6 @@ enddef; % has a tangent at $z\sb0$ equal to the first one of $z\sb{j} -z\sb0$ % that is nonzero. % -% \DescribeRoutine{__dir} % \gbc{__dir} gets the direction at point 0 for an arbitrary path. % \gbc{postdirection} % \DescribeRoutine{postdirection} @@ -7815,7 +8512,8 @@ enddef; % centered at the center of the dot and rotated 45 degrees, will encompass % the whole square (theoretically). % \begin{macrocode} -path cut_path; cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle; +path cut_path; +cut_path := (.5,0)--(.5,.71)--(-.5,.71)--(-.5,0)--cycle; % \end{macrocode} % @@ -7875,6 +8573,7 @@ enddef; % \end{macrocode} % +% % \subsection{Randomizing a path} % % In order to randomly change a path, we need to randomly change its @@ -7964,9 +8663,8 @@ enddef; % % \DescribeRoutine{detrivialized} % We start with a routine that strips out trivial segments from a path. -% This makes some loops a lot easier. We wouldn't want to differently -% shift the two (equal) endpoints of a trivial segment, making it -% nontrivial. +% This makes some loops a lot easier. It would be weird to differently +% shift the two (equal) endpoints of a trivial segment. % \begin{macrocode} vardef detrivialized expr f = save g; path p, g[]; g := 0; @@ -8030,12 +8728,135 @@ vardef randomlines (expr maxshift) expr f = fi enddef; +% \end{macrocode} +% +% +% \subsection{Interpolating paths} +% +% Given two cubic B\'eziers, it is straightforward to create a path that +% is ``half-way between'' them: just take its control points to be +% at the midpoint between corresponding control points of the two +% B\'eziers. Two paths made up of an equal number of B\'ezier are also +% easily interpolated. However, two paths with different numbers of +% B\'ezier segments need to be subdivided until they have an equal +% number. +% +% \DescribeRoutine{interpolatedpath} +% This command accepts a number \gbc{num}, a path or pair \gbc{P} and a +% path \gbc{Q}. It returns a path which is somewhere ``between'' \gbc{P} +% and \gbc{Q} if the number is between $0$ and $1$. The case where \gbc{P} +% or \gbc{Q} is trivial is passed on to another command which is +% considerably more efficient for that case. In the more general case, the +% paths are rewritten so that they have equal length. For example, if +% \gbc{P} has length 2 and \gbc{Q} has length 1, then \gbc{Q} is rewritten +% as\\ +% \indent \gbc{subpath (0,1/2) of Q \& subpath (1/2,1) of Q}\\ +% which follows the same course as \gbc{Q} but has the same number of +% B\'ezier parts as \gbc{P}. +% +% The splitting of \gbc{Q} shown above can, for reasons unknown to me, +% produce adjacent subpaths that do not always share an endpoint. One +% would think that \gbc{subpath (s,t) of Q} and +% \gbc{subpath (t,u) of Q} would obviously end and start, respectively, +% at \gbc{point t of Q}. Alas, they don't always. Hence, we employ +% \gbc{force_equal_ends} to to make them equal, shifting their endpoints a +% microscopic amount. +% +% If \gbc{Q} is a cycle we want the returned path to also be a cycle +% (but not otherwise). This is possible whenever the ends of \gbc{P} are +% equal. +% \begin{macrocode} +vardef interpolatedpath (expr t, P) expr Q = + if not path Q: + GBerrmsg ("Improper argument to interpolatedpath.") + "The last argument to interpolatedpath must be a path."; + if pair P: onepointpath(false, P) + else: + if path P: + P + else: + onepointpath (false, origin) + fi + fi + elseif pair P: + interpolated_pair_path (t, cycle Q, P, Q) + elseif not path P: + GBerrmsg ("Improper argument to interpolatedpath.") + "The second argument to interpolatedpath must be a pair " + & "or a path."; + Q + else: + if t=0: Q + elseif t=1: P + else: + save P_, Q_; path P_, Q_; + P_ := detrivialized P; + Q_ := detrivialized Q; + if length P_ = 0: + interpolated_pair_path (t, cycle Q, pnt0(P_), Q) + elseif length Q_ = 0: + interpolated_pair_path (t, cycle Q, pnt0(Q_), P) + else: + save G, H, n, m, k, r; + path G[], H[]; + G := H := 0; + n := length P_; m := length Q_; + k := gcd(n, m); + r := m/k; + for I=0 upto n-1: + for J=0 upto r-1: + G[incr G] := subpath (I+J/r, I+(J+1)/r) of P_; + endfor + endfor + r := n/k; + for I=0 upto m-1: + for J=0 upto r-1: + H[incr H] := subpath (I+J/r, I+(J+1)/r) of Q_; + endfor + endfor + for N = 1 upto G-1: + force_equal_ends(G[N], G[N+1]); + force_equal_ends(H[N], H[N+1]); + endfor + interpolated_segment (t, G1, H1) + for N = 2 upto G: & interpolated_segment (t, G[N], H[N]) + endfor if (pnt0(G1)=pnt1(G[G])) and (cycle Q): & cycle fi + fi + fi + fi +enddef; + +% \end{macrocode} +% \DescribeRoutine{interpolated_pair_path} +% Since we cannot rely on the cyclicity of \gbc{Q}, we pass a boolean +% parameter . That is because the second argument here might actually +% have been the first argument of \gbc{interpolatedpath}. +% \begin{macrocode} +vardef interpolated_pair_path (expr t, cyclic, P, Q) = + save N; N := length Q; + if N=0: onepointpath (cyclic, (t)[pnt0(Q),P]) + else: + (t)[pnt0(Q),P]..controls (t)[post0(Q),P] and + for n=1 upto N - 1: + (t)[pre[n](Q),P]..(t)[pnt[n](Q),P]..controls (t)[post[n](Q),P] + and + endfor + (t)[pre[N](Q),P].. if cyclic: cycle else: (t)[pnt[N](Q),P] fi + fi +enddef; + +vardef interpolated_segment (expr t, S, T) = + (t)[ pnt0(S), pnt0(T)]..controls + (t)[ post0(S), post0(T)] and (t)[ pre1(S), pre1(T)].. + (t)[ pnt1(S), pnt1(T)] +enddef; + % \end{macrocode} % % \subsection{Parallelling a path} % % \DescribeRoutine{parasegment} -% This creates a path parallel to a given cubic Bezier segment \gbc{f}. +% This creates a path parallel to a given cubic B\'ezier segment \gbc{f}. % It should be called by a command (such as \gbc{parapath}) that makes % sure \gbc{f} is nontrivial (meaning the directions are non-zero). It % splits the segment into subsegments for accuracy. Its arguments are the @@ -8088,7 +8909,7 @@ vardef parapath (expr d) expr f = path g[], h, p[], q[]; numeric a, s, t; pair u, v, w, w[]; - s := emax (3, emin (segment_split, ceiling (max_points/5/length f))); + s := emax(3, emin(segment_split, ceiling(max_points/5/length f))); p := 0; for i = 1 upto length f: h := subpath (i-1, i) of f; @@ -8156,6 +8977,7 @@ enddef; % \end{macrocode} % +% % \section{Miscellaneous}\label{misc} % % \subsection{Implementation of \mfpic{}'s \cs{plotdata} command}% @@ -8337,8 +9159,8 @@ Plus.clear := (right--(1,1)--(-1,1)--(left)--cycle) scaled .65; Cross := ((0,0)--(dir 45)--(dir -135)--(0,0)--(dir -45)--(dir 135)) scaled .65; -Cross.clear := ((0,0)--(dir -45)--dir(45)--(dir 135)--(dir -135)--cycle) - scaled .65; +Cross.clear := + ((0,0)--(dir -45)--dir(45)--(dir 135)--(dir -135)--cycle) scaled .65; Asterisk := ((0,0)--up--down--(0,0)--(dir 30)--(dir -150) --(0,0)--(dir -30)--(dir 150)) scaled .6; @@ -8384,7 +9206,8 @@ save _A; pair _A[]; SolidStar := mkstar (5, 2, _A) scaled .84; Star := undo_cycle SolidStar; Star.clear := polyline (true) - (_A9, _A10, _A1, _A2, _A3, (xpart _A3, 1), (xpart _A9, 1)) scaled .84; + (_A9, _A10, _A1, _A2, _A3, (xpart _A3, 1), (xpart _A9, 1)) + scaled .84; SolidStar.clear := Star.clear; forsuffixes S = @@ -8403,7 +9226,9 @@ endfor % have it, % \DescribeRoutine{lcm} % \gbc{lcm} is a snap. Since \gbc{gcd} always returns a positive result, -% \gbc{lcm} satisfies the usual rule for signs of products. +% \gbc{lcm} satisfies the rule for signs of products. Note that these both +% silently accept noninteger arguments, though the results may not be very +% meaningful. % \begin{macrocode} vardef gcd (expr n, m) = save a, b, r; @@ -8648,7 +9473,8 @@ def barchart (expr firstbar, sep, r, vert)(text data) = path chartbar[]; chartbar := 0; barwd := r*sep; for _itm = data: - barend[incr chartbar] := if pair _itm: ypart _itm else: _itm fi; + barend[incr chartbar] + := if pair _itm: ypart _itm else: _itm fi; barbegin[chartbar] := if pair _itm: xpart _itm else: 0 fi; endfor barbegin := barend := barlength := barstart := chartbar; @@ -8685,8 +9511,10 @@ enddef; % \end{macrocode} % +% %^^A Overlays - taken from MFbook, p 295. (Bruce Leban) % +% % \subsection{Overlays}\label{overlays} % % This final code predates me. When I inherited \mfpic{} it contained no @@ -8762,6 +9590,7 @@ numeric gcode; gcode := 0; % % \end{macrocode} % +% % \subsection{Dvips names for colors}\label{dvipsnam} % % In order to make \file{dvipsnam.mp} useful outside grafbase, we give diff --git a/Master/texmf-dist/source/generic/mfpic/mfpic.dtx b/Master/texmf-dist/source/generic/mfpic/mfpic.dtx index 5da4b773a74..586d051e18e 100644 --- a/Master/texmf-dist/source/generic/mfpic/mfpic.dtx +++ b/Master/texmf-dist/source/generic/mfpic/mfpic.dtx @@ -1,10 +1,10 @@ % \iffalse % File: mfpic.dtx -% A part of mfpic 1.06 2011/03/08 +% A part of mfpic 1.10 2012/12/03 % % ------------------------------------------------------------------- % -% Copyright 2002--2011, Daniel H. Luecking +% Copyright 2002--2012, Daniel H. Luecking % % Mfpic may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3c of this license or (at @@ -22,7 +22,7 @@ % %\ProvidesPackage{mfpic} %<*sty> - [2011/03/08 v1.06. Macros for drawing with Metafont/MetaPost.]% + [2012/12/03 v1.10. Macros for drawing with Metafont/MetaPost.]% % %<*driver> \documentclass{ltxdoc} @@ -36,6 +36,7 @@ \renewcommand \arg[1]{{\mytt \##1}} \renewcommand\#{\char`\#\relax} \renewcommand{\meta}[1]{{$\langle$\rmfamily\itshape#1\/$\rangle$}} +\newcommand{\mmarg}[1]{\marg{\meta{#1}}} \DeclareRobustCommand\cs[1]{{\mytt\char`\\#1}} \def\prog#1{{\mdseries\scshape #1}} \def\grafbase{\prog{grafbase}} @@ -57,6 +58,7 @@ \renewcommand\|{${}\mathrel{|}{}$} \makeatletter +\let\HD@SetMacroIndent\@gobble \newcommand\bsl{{\mytt\@backslashchar}} % Stupid lists! \def\@listi{\leftmargin\leftmargini @@ -106,7 +108,7 @@ \end{document} % %\fi -% \CheckSum{5145} +% \CheckSum{5188} % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z @@ -134,15 +136,17 @@ % produce the picture. The picture is then included on a second pass % through \TeX. % -% This file documents the source code. See \file{mfpic-doc.pdf}/\file{tex} -% for the user documentation, or \file{mfpguide.pdf}/\file{tex}) for an -% introductory guide. +% This file documents the \mfpic{} source code. The user manual for +% \mfpic{} is distributed as \file{mfpic-doc.pdf}, produced from +% \file{mfpic-doc.tex}. An introductory guide to \mfpic{} is available +% in \file{mfpguide.pdf}, produced from \file{mfpguide.tex} % \end{abstract} % % \StopEventually{\PrintIndex} % \tableofcontents % % +% % \section{Introductory setup}\label{intro} % % \Mfpic{} is designed to work with plain \TeX, \LaTeX, \pdfTeX, and @@ -170,9 +174,9 @@ \ifx\mfpfileversion\UndEfInEd\else\expandafter\endinput\fi% {% \catcode\lq\.12 \catcode\lq\/12% - \gdef\mfpfileversion{1.06}% - \gdef\mfpfiledate{2011/02/25}% - \gdef\mfpicversion{106}% + \gdef\mfpfileversion{1.10}% + \gdef\mfpfiledate{2012/12/03}% + \gdef\mfpicversion{110}% }% % \end{macrocode} % @@ -185,8 +189,6 @@ % \end{macrocode} % % We now get rid of unusually catcoded punctuation, space and EOL. -% We save all the current category codes in the macro \cs{mfp@restoreALL} -% and restore them at the end by executing this command. % We assume that letters, numbers, `\texttt\bsl', `\texttt\{', `\texttt\}', % `\texttt\#' and `\texttt\%' have the usual categories. However, styles % (e.g., \prog{french}) that make punctuation active foul up \cs{write}\,s @@ -201,9 +203,9 @@ \catcode96=12 % 96=left quote \catcode`\@=11 \gdef\MFPsavecodes{% - \edef\mfp@restoreNLchar{\newlinechar\number\newlinechar\relax}% - \edef\mfp@restoreELchar{\endlinechar\number\endlinechar\relax}% - \edef\mfp@restoreSP{\catcode32=\number\catcode32\relax}% + \edef\mfp@restoreNLC{\newlinechar\number\newlinechar\relax}% + \edef\mfp@restoreELC{\endlinechar\number\endlinechar\relax}% + \edef\mfp@restoreSPA{\catcode32=\number\catcode32\relax}% \edef\mfp@restoreEOL{\catcode13=\number\catcode13\relax}% \edef\mfp@restoreALL{\mfp@restorecode{=}\mfp@restorecode{@}% \mfp@restorecode{$}\mfp@restorecode{:}\mfp@restorecode{;}% @@ -213,8 +215,8 @@ \mfp@restorecode{>}\mfp@restorecode{*}\mfp@restorecode{/}% \mfp@restorecode{+}\mfp@restorecode{-}\mfp@restorecode{"}% \mfp@restorecode{'}\mfp@restorecode{_}\mfp@restorecode{`}% - \mfp@restoreEOL\mfp@restoreSP\catcode10=\number\catcode10 - \mfp@restoreNLchar\mfp@restoreELchar}}% + \mfp@restoreEOL\mfp@restoreSPA\catcode10=\number\catcode10 + \mfp@restoreNLC\mfp@restoreELC}}% \gdef\mfp@restorecode#1{\catcode`\string#1=\number\catcode`#1\relax}% \ifx\@makeother\UndEfInEd \gdef\@makeother#1{\catcode`#1=12\relax}\fi \gdef\MFPsanitize{\endlinechar13 \newlinechar10 @@ -232,7 +234,7 @@ % \end{macrocode} % % \cs{MFPsavecodes} saves a bunch of things that must have (mostly) -% normal settings \cs{mfp@restoreALL} will be invoked at the end of the +% normal settings. \cs{mfp@restoreALL} will be invoked at the end of the % file to restore all the values. % % \cs{MFPsanitize} sets (almost) everything to normal. It can be used to @@ -240,6 +242,7 @@ % necessary. Characters 10 and 13 are \verb|^^J| and \verb|^^M|, % control-J and control-M. % +% % \subsection{Debugging and messages}\label{debug} % % \DescribeMacro{\mfpicdebug} @@ -290,6 +293,7 @@ \def\mfp@lineno{line \number\inputlineno\space in the TeX source}% % \end{macrocode} % +% % \subsection{Detecting the format}\label{format} % % To detect its environment, \mfpic{} needs to test whether certain @@ -359,12 +363,21 @@ % we are not in \AmSTeX{}. We used to detect \AmSTeX{} by checking % \cs{fmtname}. This leads to problems if some other format inputs % \file{amstex.tex} and redefined \cs{fmtname}. Thus we will now check -% \cs{amstexloaded@}. +% \cs{amstexloaded@}. Unfortunately, \file{amstex.tex} sets it equal to +% \cs{relax}, which is much too easy to be the result of some other +% attempt to check it. Thus, we add an additional check for +% \cs{NoBlackBoxes}. % \begin{macrocode} \newif\ifmfp@latex \mfp@latexfalse \mfp@ifdefined\documentstyle - {\ifx \amstexloaded@\relax \mfp@DBlog{AmS-TeX detected.}% - \else \mfp@DBlog{LaTeX detected.}\mfp@latextrue + {\ifx \amstexloaded@\relax % amstex loaded, or a bad check for it + \ifx\NoBlackBoxes\UndEfInEd % amstex not loaded + \mfp@DBlog{LaTeX detected.}\mfp@latextrue + \else % most likely amstex loaded + \mfp@DBlog{AmS-TeX detected.}% + \fi + \else % amstex not loaded + \mfp@DBlog{LaTeX detected.}\mfp@latextrue \fi}% {\mfp@DBlog{Neither LaTeX nor AmS-TeX detected.}}% % \end{macrocode} @@ -391,6 +404,7 @@ {\mfp@DBlog{Not pdfTeX.}}% % \end{macrocode} % +% % \subsection{Blank line and spacing hacks}\label{spacing} % % In order for commands to always read their arguments correctly, @@ -426,6 +440,7 @@ \mfp@enddef % \end{macrocode} % +% % \subsection{Warning if commands are already defined} % % We sometimes (either by accident or by choice) redefine things defined @@ -454,6 +469,7 @@ \newdef\newlet#1{\mfp@testdef#1\let#1}% % \end{macrocode} % +% % \subsection{Error messages and warnings} % % If one tries to switch on \MP{} support after the output file has been @@ -524,7 +540,7 @@ % \end{macrocode} % % This message is issued when the \cs{tlabeljustify} command (see -% section~\ref{labelsettings}) is issued with an invalid parameter. +% subsection~\ref{labelsettings}) is issued with an invalid parameter. % \begin{macrocode} \newdef\mfp@justify@error{% \mfp@errmsg{Invalid justification parameter for text label}% @@ -538,12 +554,14 @@ % warning, which is otherwise issued by \cs{mfpendloop}. % \begin{macrocode} \newdef\mfp@untilwarn{% - \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!}}% + \Mfpic@warn{\mfp@b mfploop without \string\mfpuntil!\@nl}}% % \end{macrocode} % % +% % \section{Configuring \mfpic{} behavior}\label{configuring} % +% % \subsection{Options}\label{options} % % \DescribeMacro{\ifmfpmpost} @@ -636,7 +654,7 @@ % \gbc{setvariable(color)}.) For simplicity, we do this with all data % types. For example \cs{setmfvariable}\marg{numeric} writes % `\gbc{setnumeric}'. This makes spaces significant in the first argument, -% so we strip them off the ends with \cs{MFP@sp@def} (defined in +% so we strip them off the ends with \cs{mfp@sp@def} (defined in % section~\ref{optional}). % % We have abbreviations for the most common internal uses. For example @@ -655,7 +673,7 @@ % spaces are significant. % \begin{macrocode} \newdef\setmfvariable#1{% - \MFP@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}% + \mfp@sp@def\mfp@tempa{#1}\@setmfvariable\mfp@tempa}% \newdef\@setmfvariable#1#2#3{% \mfp@ifopengraphsfile% {\mfcmd{set#1 (#2) #3}}% @@ -665,7 +683,7 @@ \newdef\setmfpair {\@setmfvariable{pair}}% \newdef\setmfcolor {\@setmfvariable{color}}% \newdef\globalsetmfvariable#1#2#3{% - \MFP@sp@def\mfp@tempa{#1}% + \mfp@sp@def\mfp@tempa{#1}% \mfp@ifopengraphsfile {\mfcmd{\ifx\mfp@tempa\mfp@C gsetcolor \else gsetvariable (#1) \fi (#2) #3}}% @@ -864,9 +882,10 @@ \newlet\ifmfp@readlog\iffalse \newdef\mfpreadlog{% \mfp@ifopengraphsfile - {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}% + {\mfp@afteropen@error\mfpreadlog}{\global\let\ifmfp@readlog\iftrue}}% % \end{macrocode} % +% % \subsection{Graphic inclusion}\label{graphic} % % \DescribeMacro{\mfpicllx} @@ -918,7 +937,7 @@ \newdef\nofile@setmfpgraphic#1{% {\edef\mfp@tempa{#1}% \vbox to 0pt{\vss - \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}% + \rlap{\kern2pt \mfpdraftfont \mfp@sanitized\mfp@tempa}\kern 2pt}}}% \mfp@ifdefined\strip@prefix{}{\def\strip@prefix#1>{}}% \newdef\mfp@sanitized{\@xp\strip@prefix\meaning}% \newlet\@setmfpicgraphic\normal@setmfpgraphic @@ -998,6 +1017,7 @@ % % \end{macrocode} % +% % \subsection{\LaTeX{} options and \MP{} graphics inclusion}\label{latex} % % Code dependent on \LaTeXe. Mostly this is the option processing @@ -1155,6 +1175,7 @@ % \end{macrocode} % % +% % \section{Optional parameter handling}\label{optional} % % We borrow \LaTeX's \cs{@ifnextchar}. The first argument is the token @@ -1182,7 +1203,7 @@ \fi \reserved@c}% {% - \def\:{\global\let\@sptoken= }\: % this makes \@sptoken a space token + \def\:{\global\let\@sptoken= }\: % makes \@sptoken a space token \def\:{\@xifnch}\@xp\gdef\: {\futurelet\@let@token\@ifnch}% }% \mfp@enddef @@ -1193,18 +1214,23 @@ % \file{keyval}, that is \cs{KV@@sp@def}; we copy it here with name % changes. Defining \cs{mfp@tempa}, and then calling it with a space as % argument, ensures there will be an actual space token where needed in -% the definition of \cs{MFP@sp@def}. +% the definition of \cs{mfp@sp@def}. The first argument is the control +% sequence to define and the second is its definition text, with possible +% spaces to be stripped. (I'm wondering now why I didn't just use +% \cs{zap@space} since there shouldn't be \emph{any} significant spaces. +% Well, at least I have the code in place for a future key-value +% interface.) % \begin{macrocode} \def\mfp@tempa#1{% - \def\MFP@sp@def##1##2{% - \futurelet\mfp@next\MFP@sp@d##2\@nil\@nil#1\@nil\relax##1}% - \def\MFP@sp@d{% - \ifx\mfp@next\@sptoken \expandafter\MFP@sp@b - \else \expandafter\MFP@sp@b\expandafter#1% + \def\mfp@sp@def##1##2{% + \futurelet\mfp@next\mfp@sp@d##2\@nil\@nil#1\@nil\relax##1}% + \def\mfp@sp@d{% + \ifx\mfp@next\@sptoken \@xp\mfp@sp@b + \else \@xp\mfp@sp@b\@xp#1% \fi}% - \def\MFP@sp@b#1##1 \@nil{\MFP@sp@c##1}}% + \def\mfp@sp@b#1##1 \@nil{\mfp@sp@c##1}}% \mfp@tempa{ }% -\def\MFP@sp@c#1\@nil#2\relax#3{\mfp@toks{#1}\edef#3{\the\mfp@toks}}% +\def\mfp@sp@c#1\@nil#2\relax#3{\mfp@toks{#1}\edef#3{\the\mfp@toks}}% % \end{macrocode} % % The following save us some typing whenever we need to check if some @@ -1252,12 +1278,12 @@ % that seems impossible (or impossibly hard). % \begin{macrocode} {% - \catcode`Q3 \catcode`\~12 - \gdef\mfp@ifempty#1{\if~#1~\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% - \gdef\mfp@ifexist#1{\if~#1~\@xp\@gobble\else\@xp\@firstofone\fi}% - \gdef\mfp@emptysub#1#2{\if~#1~#2\else#1\fi}% - \long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}% - \long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}% +\catcode`Q3 \catcode`\~12 +\gdef\mfp@ifempty#1{\if~#1~\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}% +\gdef\mfp@ifexist#1{\if~#1~\@xp\@gobble\else\@xp\@firstofone\fi}% +\gdef\mfp@emptysub#1#2{\if~#1~#2\else#1\fi}% +\long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil}% +\long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4}% }% % \end{macrocode} % @@ -1280,7 +1306,7 @@ % code. % \begin{macrocode} \newdef\mfp@defaultopt#1#2{% - \@ifnextchar[{\mfp@ifemptyopt{#1}{#2}}{#1{#2}}}% + \@ifnextchar[{\mfp@ifemptyopt{#1}{#2}}{#1{#2}}}%] \newdef\mfp@ifemptyopt#1#2[#3]{\mfp@ifempty{#3}{#1{#2}}{#1{#3}}}% \newdef\mfp@nullopt#1{\@ifnextchar[{\mfp@getopt{#1}}{#1{}}}% \newdef\mfp@getopt#1[#2]{#1{#2}}% @@ -1305,8 +1331,10 @@ % to indicate the default, minimizing the extra typing. % % +% % \section{Writing to the \file{.mf} or \file{.mp} file}\label{writing} % +% % \subsection{Preserving linebreaks}\label{linebreaks} % % Some macros (the ones we call list macros) can take quite long @@ -1415,6 +1443,7 @@ \mfp@ifdefined\@safe@activesfalse\@safe@activesfalse{}}% % \end{macrocode} % +% % \subsection{Initializing the output file}\label{output} % % Category 12 characters percent, sharp and backslash signs for the @@ -1460,8 +1489,6 @@ % can be plotted against its sequence position. % \item \cs{mfp@toks} Temporary token register. % \item \cs{mfp@verbtex} A temporary token list used by \cs{mfpverbtex}. -% \item \cs{mfp@commonverbatimtex} Tokens written at the start of every -% output file inside a \mfc{verbatimtex} group. % \item \cs{ifmfp@switch} Not exactly a register, but a temporary % switch for passing information from one macro to another. % \end{itemize} @@ -1475,15 +1502,13 @@ \newcount\mfp@sequence \newtoks\mfp@toks \newtoks\mfp@verbtex -\newtoks\mfp@commonverbatimtex \newif\ifmfp@switch +% % \end{macrocode} % % We store most of the \mfc{verbatimtex} block that \mfpic{} relies on in -% the token register \cs{mfp@commonverbatimtex}. We do that because it -% relies on a couple of catcode changes and we want to be in a situation -% where we have that under control. Each line will end with an active -% ctrl-M, which is transformed by \cs{mfsrc} into a newline. +% the file \file{mfpicdef.tex}. This is the code that goes into that +% file % % The \cs{mpxshipout} is to cover all three cases of the output of % `\texttt{mpto -tex}'. In public versions of \MP{} prior to 0.9 there was @@ -1494,21 +1519,42 @@ % \mfc{btex} and so will overwrite my definition. Thus all cases are % served. % \begin{macrocode} -\begingroup - \mfp@keeplines\@makeother\#% - \@makeother\%\global\mfp@commonverbatimtex - {\gdef\mpxshipout{\afterassignment\middlempxshipout\setbox0=\hbox}% - \gdef\middlempxshipout{\aftergroup\finishmpxshipout}% - \gdef\finishmpxshipout{\dimen1=\ht0 \dimen2=\dp0 - \dimen0=\dimen1 \advance\dimen0\dimen2 - \setbox0=\hbox{\hbox{\box0 - \ifnum\dimen0>0 \vrule width1sp height\dimen1 depth\dimen2 - \else \vrule width1sp height1sp depth0sp\relax - \fi}}% - \ht0=0pt \dp0=0pt \shipout\hbox{\box0}}% - \def\MFPtext#1{\vbox{\def\\{\cr}\MFPcfont\everylabel - \halign{##\hfil\cr#1\crcr}}}% - }\endgroup% +%<*defs> +\gdef\mpxshipout{\afterassignment\middlempxshipout\setbox0=\hbox}% +\gdef\middlempxshipout{\aftergroup\finishmpxshipout}% +\gdef\finishmpxshipout{\dimen1=\ht0 \dimen2=\dp0 + \dimen0=\dimen1 \advance\dimen0\dimen2 + \setbox0=\hbox{\hbox{\box0 + \ifnum\dimen0>0 \vrule width1sp height\dimen1 depth\dimen2 + \else \vrule width1sp height1sp depth0sp\relax + \fi}}% + \ht0=0pt \dp0=0pt \shipout\hbox{\box0}}% +\def\MFPtext#1{\vbox{\def\\{\cr}\MFPcfont\MFPeverylabel + \halign{##\hfil\cr#1\crcr}}}% +% \end{macrocode} +% +% There are vague plans to make the output file equally usable by \MF{} +% and \MP{}. For this to work, \file{grafbase.mf} defines +% \mfc{verbatimtex} to gobble everything to the next colon (which we place +% after each \mfc{etex} we write). This fails if there is a +% \verb$\begingroup$ without matching \verb$\endgroup$ because \MF{} sees +% this as the command \verb$\$ (meaning \mfc{relax}) followed by the \MF{} +% primitive \mfc{begingroup}. But \MF{} doesn't allow gobbled text +% parameters to contain unbalanced groups. Thus, we use the replacements +% defined here, hidden from \MF{} in a \TeX{} input file. +% \begin{macrocode} +\let\MFPbegingroup\begingroup +\let\MFPendgroup\endgroup +% +% \end{macrocode} +% +% Within \file{mfpic.tex} these commands can be anything unexpandable, +% since we just want them to be written verbatim. It makes sense to give +% them the obvious meanings. +% \begin{macrocode} +%<*tex> +\let\MFPbegingroup\begingroup +\let\MFPendgroup\endgroup % \end{macrocode} % % We store the first several lines that will be written to the output @@ -1616,8 +1662,8 @@ verbatimtex\@nl \ifmfp@verbtex \the\mfp@verbtex\@nl \fi \relax\@nl - \the\mfp@commonverbatimtex - \def\noexpand\everylabel{\the\mfp@toks}\@nl + \noexpand\input mfpicdef.tex\relax\@nl + \def\noexpand\MFPeverylabel{\the\mfp@toks}\@nl etex;\@nl \mfp@ifdefined\mfp@settemplate\mfp@settemplate{}% }% @@ -1648,7 +1694,7 @@ % braces and spaces aren't touched. % \begin{macrocode} \def\mfp@dospecials{\do\$\do\&\do\#\do\^\do\_\do\%\do\~}% -% +% \end{macrocode} % \DescribeMacro{\opengraphsfile} % This is the main command to set up the output file. % The name of the output file is its only parameter, and it appends @@ -1739,6 +1785,7 @@ \fi \global\let\mfp@filename\UndEfInEd}{}}% % \end{macrocode} % +% % \subsection{Information from \MF: reading its log file} % % \DescribeMacro{\assignmfvalue}\SpecialUsageIndex{\globalassignmfvalue} @@ -1786,7 +1833,8 @@ {\mfp@msg{}\Mfpic@msg{No value for \string#2\ifin@mfpicenv\space in mfpic figure \number\mfp@count\fi.\@nl}}% {}% - \mfsrc{\@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}% + \mfsrc{% + \@ifmplabels{\@nl verbatimtex #1\def\string#2{#2} etex;\@nl}{}% message "\string\mfpicvalue";\@nl message "\mfp@cmdname#2";\@nl show #3;\@nl @@ -1831,6 +1879,7 @@ % \end{macrocode} % % +% % \section{\Mfpic{} dimensions}\label{dimensions} % % A number of packages, especially figure drawing packages, allocate a @@ -2090,6 +2139,7 @@ % \end{macrocode} % % +% % \section{Helper macros}\label{helper} % % \DescribeMacro{\mfpicnumber} @@ -2177,7 +2227,7 @@ \newdef\colorarray{\setmfarray{color}}% \newdef\rgbcolorarray{\setmfarray{rgbcolor}}% \newdef\cmykcolorarray{\setmfarray{cmykcolor}}% -\newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1) (#2)}\mfp@writedata}% +\newdef\globalsetmfarray#1#2{\mfsrc{gsetarray (#1)(#2)}\mfp@writedata}% \newlet\globalsetmparray\globalsetmfarray % \end{macrocode} % @@ -2279,6 +2329,7 @@ % \end{macrocode} % % +% % \section{Macros to implement prefix commands}\label{prefix} % % Some \mfpic{} macros, like \cs{circle} create a path. When used without @@ -2395,7 +2446,7 @@ % default color, but we provide a command for the user to change it. % \begin{macrocode} \newdef\mfp@render{\draw[]}% -\newdef\setrender#1{\mfp@def\mfp@render{#1}}% +\newdef\setrender{\mfp@def\mfp@render}% % \end{macrocode} % % A figure macro will invoke the common first-stage code and the rendering @@ -2455,6 +2506,7 @@ % \end{macrocode} % % +% % \section{Macros for getting data from files}\label{rwdata} % % The following command contains the common code to open a data file for @@ -2588,8 +2640,9 @@ \fi}% % \end{macrocode} % +% \section{Various \mfpic{} Settings.}\label{mfpsettings} % -% \section{Various \CMF{} Settings.}\label{MFsettings} +% \subsection {\CMF{} settings}\label{MFsettings} % % \DescribeMacro{\penwd} % Macros that write changes in default \grafbase{} variables now use the @@ -2651,8 +2704,8 @@ \newdef\settension#1{\setmfnumeric{default_tension}{#1}}% % \end{macrocode} % -% -% \section{Settings for text label placement in figures}\label{labelsettings} +% \subsection{Settings for text label placement in figures} +% \label{labelsettings} % % \cs{tlabel}\,s are `justified' by placing a particular point of the % text at the location specified. The \cs{tlabel} command accepts an @@ -2781,7 +2834,7 @@ \mfp@ifmpost {\mfp@ifopengraphsfile {\mfcmd{verbatimtex\@nl - \def\noexpand\everylabel{\the\mfp@toks} etex}}% + \def\noexpand\MFPeverylabel{\the\mfp@toks} etex}}% {}}% {}}% \newdef\every@tlabel{}% @@ -2795,8 +2848,7 @@ \newdef\pinumber{3.14159}% % \end{macrocode} % -% -% \section{Other settings}\label{othersettings} +% \subsection{Other settings}\label{othersettings} % % \DescribeMacro{\headshape} % This sets the arrowhead shape. The parameters are: the ratio of width @@ -2867,7 +2919,8 @@ % command name has the string `\texttt{color}', but the color does not. % \begin{macrocode} \newdef\mfpdefinecolor#1#2#3{\setmfcolor{#1}{#2(#3)}}% -\newdef\mfp@defclr#1#2#3{\setmfcolor{#1}{\mfp@ifempty{#2}{#3}{#2(#3)}}}% +\newdef\mfp@defclr#1#2#3{% + \setmfcolor{#1}{\mfp@ifempty{#2}{#3}{#2(#3)}}}% \newdef\mfp@newcolorcmd#1{% \@namedef{#1\mfp@C}{\mfp@nullopt{\mfp@defclr{#1\mfp@C}}}}% \mfp@newcolorcmd{draw}\mfp@newcolorcmd{fill}\mfp@newcolorcmd{tlabel}% @@ -3037,7 +3090,7 @@ the following letters: x, y, l, b, r, or t. If you proceed, ^^J% x will be assumed.}\def\mfp@axisnum{0}\def\mfp@axisletter{x}}% {\edef\mfp@axisnum{\@nameuse{mfp@axis@#1}}\def\mfp@axisletter{#1}}% - \edef\mfp@defheadlen{% + \edef\mfp@defaultheadlen{% \the\ifnum\mfp@axisnum>1 \sideheadlen\else \axisheadlen\fi}}% % \end{macrocode} % @@ -3202,6 +3255,8 @@ \newdef\mfp@additions{}% % \end{macrocode} % +% +% % \section{The user level graphics macros} % % This is the start of the definition of \cs{mfp@grafmacs}. It contains @@ -3213,10 +3268,11 @@ \newdef\mfp@grafmacs{% % \end{macrocode} % +% % \subsection{Figure macros}\label{figure} % % These are the figure macros. These are implemented as \MF{} paths that -% can be variously rendered, transformed, etc., with the prefix macros of +% can be variously rendered, transformed, etc., by the prefix macros of % subsection~\ref{prefixcommands}. % % Most of the \mfpic{} graphic commands take optional arguments. Most of @@ -3235,6 +3291,7 @@ % its syntax in use. For those that call an \cs{mfp@} version, the % implementation is in the next section. % +% % \subsubsection{Common geometric objects}\label{geometric} % % The first few (\cs{rect} through \cs{sector}) are closed paths and @@ -3317,6 +3374,31 @@ \newdef\ellipse{\mfp@defaultopt\mfp@ellipse{0}}% % \end{macrocode} % +% \DescribeMacro{\quarterellipse} +% \DescribeMacro{\halfellipse} +% \DescribeMacro{\fullellipse} +% The next three commands simply call \grafbase{} commands of the same +% name. They draw part or all of an ellipse inscribed in a parallelogram. +% Each requires for its argument three points, separated by commas. For +% \cs{quarterellipse} these points are, respectively, the midpoint of one +% side of a parallelogram, a corner point on that side, and the midpoint +% of the side adjacent to the first at that corner. For \cs{halfellipse} +% they are the midpoints of three successive sides. For \cs{fullellipse} +% they are the center and the midpoints of two adjacent sides. They are +% all simple figmacs with no optional arguments and no star forms. +% +% It would be possible to give all of them the same three arguments, +% for example those of \cs{fullellipse}, but I wanted to put the +% endpoints of the paths into the argument list. The reason +% \cs{quarterellipse} is passed the corner point instead of the center is +% because of the intended use: rounding off an asymmetric corner without +% having to compute the center of the parallelogram. +% \begin{macrocode} + \newdef\quarterellipse##1{\mfp@figmac{quarterellipse (##1)}}% + \newdef\halfellipse##1{\mfp@figmac{halfellipse (##1)}}% + \newdef\fullellipse##1{\mfp@figmac{fullellipse (##1)}}% +% \end{macrocode} +% % \DescribeMacro{\sector} % This is the closed curve starting at the center of a circle, out % along a radius to the circumference of the circle, along an arc of the @@ -3361,7 +3443,8 @@ \newdef\arc{\mfp@iftoken*{\arccomplement\mfp@arc}{\mfp@arc}}% % \end{macrocode} % -% This final circle is for we complex function theorists. It makes a +% \DescribeMacro{\pshcircle} +% This final circle is for us complex function theorists. It makes a % `pseudohyperbolic circle'. This requires a point $z$ inside the circle % with center $(0,0)$ and radius $1$, and a radius $R < 1$. It produces % a circle with $R$ as its pseudohyperbolic radius and $z$ as its @@ -3371,6 +3454,18 @@ \newdef\pshcircle{\mfp@ifstar\mfp@pshcircle\mfp@F\mfp@T}% % \end{macrocode} % +% \DescribeMacro{\hypergeodesic} +% And this final arc is also for we complex function theorists. It makes a +% `hyperbolic geodesic'. This requires two points $z$ and $w$ inside the +% circle $T$ with center $(0,0)$ and radius $1$. It produces a circular arc +% from the first point to the second on the unique circle that passes +% through these two points and meets $T$ at right angles. The star form +% switches contexts to the upper half-plane. +% \begin{macrocode} + \newdef\hypergeodesic{\mfp@ifstar\mfp@hypergeodesic{UHP}{UD}}% +% \end{macrocode} +% +% % \subsubsection{List macros}\label{list} % % The figure macros of this section are all list macros. They produce a @@ -3514,7 +3609,7 @@ % in the list. If the optional argument is absent (or empty), the % \grafbase{} command that is written takes only a boolean argument % (closed or not closed) followed by the list of points. If the tension -% argument is present, a different comamnd is written that also has a tension +% argument is present, a different command is written that also has a tension % argument. The command name is almost the same, but has a `\gbc{t}' % prepended. The default tension is the \cs{grafbase}{} variable % \gbc{default_tension}, set with \cs{settension}, initialized to 1. @@ -3589,16 +3684,6 @@ \newdef\turtle{\mfp@listmac{turtle}}% % \end{macrocode} % -% \DescribeMacro{\brownianmotion} -% Used by me once to ilustrate Brownian motion. The argument consists of -% a starting point, the number of steps, and a scale factor, separated -% by commas. It draws a polyline starting with the starting point moving -% in a random direction a random distance, then repeating that from the -% new point, etc., for the number of steps given. The size of each step is -% random, but the scale factor gives the average size. -% \begin{macrocode} - \newdef\brownianmotion##1{\mfp@figmac{brownianpath (##1)}}% -% \end{macrocode} % % \subsubsection{Graphing functions}\label{functions} % @@ -3687,7 +3772,7 @@ % example,\\ % \indent\verb$\levelcurve[p]{(0,0),0.1}{x*x + y*y < 3}$\\ % will draw approximately the circle with radius $\sqrt3$ as a sequence of -% line segments with length $0.1$. That will require about 108 segments. +% line segments with length $0.1$. That will require about 109 segments. % Its parameters are similar enough to those of \cs{function} that we % can use the same interface. % \begin{macrocode} @@ -3695,19 +3780,19 @@ % \end{macrocode} % % We now define two macros for depicting the solution of an -% ordinary differential equation. THe first of these, \cs{DEgraph}, -% produces the graph of solutions of equations of the form +% ordinary differential equation. The first of these, \cs{DEgraph}, +% produces the graph of the solution for equations of the form % $$ -% \frac{dy}{dx} = f(x,y),\quad y(x_0) = y_0. +% \frac{dy}{dx} = f(x,y),\quad y(x\sb0) = y\sb0. % $$ -% The data required are the \emph{initial values} (the two numbers $x_0$ -% and $y_0$), the formula $f(x,y)$ (an explicit \MF{} numerical expression -% with literal variables \mfc{x} and \mfc{y} as the only unknowns. Since -% the \MF{} and only handle paths connecting discrete points, also -% required is a step size which, roughly speaking, is the distance between -% points in graph coordinates, and the number of steps $N$ to use. The \MF{} -% macros then calculate $N$ additional points (the first is $(x_0,y_0)$) and join -% them together to produce the graph. +% The data required are the \emph{initial values} (the two numbers $x\sb0$ +% and $y\sb0$), the formula $f(x,y)$ (an explicit \MF{} numerical +% expression with literal variables \mfc{x} and \mfc{y} as the only +% unknowns. Since \MF{} can only handle paths connecting discrete points, +% also required is a step size which, roughly speaking, is the distance +% between points in graph coordinates, and the number of steps $N$ to use. +% The \MF{} macros then calculate $N$ additional points (the first is +% $(x\sb0,y\sb0)$) and join them together to produce the graph. % % The second macro, \cs{DEtrajectory}, draws the trajectory of a % two-dimentional differential equation of the form @@ -3719,7 +3804,7 @@ % require three dimensions to indicate the relation between $x$, $y$, and % $t$. Mathematicians call it a trajectory, and it only shows the % two-dimensional path followed by the moving object. The required data -% are an initial point $(x_0,y_0)$, the formula for the right-hand side +% are an initial point $(x\sb0,y\sb0)$, the formula for the right-hand side % (an explicit \MF{} pair-valued expression or a pair of numerical % expressions in parentheses, with literal variables \mfc{x}, \mfc{y} and % \mfc{t} as the only unknowns. Also required are a step size and the @@ -3742,19 +3827,47 @@ % % Thus our macros require the user to supply a parameter that will be % interpreted as a distance step: if $h$ is this parameter, instead of -% finding values of $y$ at $x_0$, $x_0+h$, $x_0+2h$, etc., it finds points -% $(x_n,y_n)$ on the graph so that the two-dimensional distance from $(x_0,y_0)$ -% to $(x_1,y_1)$ is $h$, then the distance from $(x_1,y_1)$ to $(x_2,y_2)$ -% is also $h$, etc. The resulting graph therefore simply follow the graph -% of $y = 1/(1-x)$ a distance roughly $Nh$ and numerical overflow is -% impossible unless the value of $Nh$ exceeds \MF{}'s size limits. -% -% There is an optional smoothness parameter as in \cs{function}. +% finding values of $y$ at $x\sb0$, $x\sb{0+h}$, $x\sb{0+2h}$, etc., it +% finds points $(x\sb{n},y\sb{n})$ on the graph so that the +% two-dimensional distance from $(x\sb0,y\sb0)$ to $(x\sb1,y\sb1)$ is $h$, +% then the distance from $(x\sb1,y\sb1)$ to $(x\sb2,y\sb2)$ is also $h$, +% etc. The resulting graph therefore simply follow the graph of $y = +% 1/(1-x)$ a distance roughly $Nh$ and numerical overflow is impossible +% unless the value of $Nh$ exceeds \MF{}'s size limits. There is an +% optional smoothness parameter as in \cs{function}. % \begin{macrocode} \newdef\DEgraph{\mfp@fcn{odeRKIV}s}% \newdef\DEtrajectory{\mfp@fcn{xyRKIV}s}% % \end{macrocode} % +% \DescribeMacro{\brownianmotion} +% Used by me once to ilustrate Brownian motion. The argument consists of +% a starting point, the number of steps, and a scale factor, separated +% by commas. It draws a polyline starting with the starting point moving +% in a random direction a random distance, then repeating that from the +% new point, etc., for the number of steps given. The size of each step is +% random, but the scale factor gives the average size. +% +% \DescribeMacro{\browniangraph} +% This approximates the graph of one-dimensional Brownian motion. The +% argument consists of the number of steps and a scale factor/step size, +% separated by commas. It draws a polyline starting at $(0,0)$, moving +% right by the step size and up or down (randomly chosen) by a random +% amount, then repeating that from the new point, etc., for the number of +% steps given. +% +% \DescribeMacro{\randomwalk} +% This is a two dimensional random walk. The argument consists of a +% starting point, the number of steps, and a distance, separated by +% commas. Like \cs{brownianmotion}, it draws a polyline starting at the +% starting point, moving in a random direction, but for this command it +% always moves a fixed distance. +% \begin{macrocode} + \newdef\brownianmotion##1{\mfp@figmac{brownianpath (##1)}}% + \newdef\browniangraph##1{\mfp@figmac{browniangraph (##1)}}% + \newdef\randomwalk##1{\mfp@figmac{randomwalk(##1)}}% +% \end{macrocode} +% % % \subsection{Plotting data from files}\label{datafiles} % @@ -3775,8 +3888,10 @@ \newdef\datafile{\mfp@nullopt\mfp@datafile}% % \end{macrocode} % +% % \subsection{The prefix commands}\label{prefixcommands} % +% % \subsubsection{Storing and reusing a figure}\label{storing} % % \DescribeMacro{\store} @@ -3811,6 +3926,13 @@ % \cs{mfobj}\marg{\meta{name}} is a figure macro, and should act exactly % the same as if the figure macro that had been stored in the variable % were typed in its place. Its one argument is the variable name. +% +% Instead of the variable name, the argument can contain any reasonable +% \MF{} path expression. In this context ``reasonable'' means it should +% contain no special \TeX{} characters that might expand upon being +% written to the output file. In particular, the backslash and `\verb$~$' +% should especially be avoided. +% % \DescribeMacro{\mpobj} % The macro \cs{mpobj} is just another name for the same command. % \begin{macrocode} @@ -3839,6 +3961,7 @@ \newdef\putmfpimage##1{\mfsrc{\@nl putimage (##1)}\mfp@writedata}% % \end{macrocode} % +% % \subsubsection{Subpaths} % % \DescribeMacro{\cutoffbefore} @@ -3986,7 +4109,8 @@ % takes an additional argument, in this case, the first mandatory argument % of \cs{plot}. % \begin{macrocode} - \newdef\plot{\mfp@optrendii{doplot}{\the\pointsize,\the\symbolspace}}% + \newdef\plot{% + \mfp@optrendii{doplot}{\the\pointsize,\the\symbolspace}}% % \end{macrocode} % % \DescribeMacro{\plotnodes} @@ -4018,6 +4142,7 @@ \newdef\showcontrols{\mfp@optrendii{showcontrols}{\the\pointsize}}% % \end{macrocode} % +% % \subsubsection{Closing a curve}\label{closing} % % There are several commands used to close paths (by prefixing them to @@ -4033,6 +4158,7 @@ % \DescribeMacro{\sclosed} % The first, \cs{sclosed}, closes smoothly in the same manner that % \cs{curve} creates a smooth path. +% % \DescribeMacro{\bclosed} % The second, \cs{bclosed}, uses an ordinary \MF{} B\'ezier. These two % have an optional argument: the amount of tension to put in the @@ -4046,6 +4172,7 @@ % The macro \cs{cbclosed} computes a closure by calculating cubic B-spline % control points from the path data and then generating a connecting % spline (see \cs{cspline}). +% % \DescribeMacro{\qbclosed} % The macro \cs{qbclosed} is similar, but quadratic B-splines are used. % @@ -4072,6 +4199,7 @@ \newdef\makesector{\mfp@modmac{makesector}}% % \end{macrocode} % +% % \subsubsection{Filling a closed curve}\label{filling} % % The next few prefix macros fill the interior of the closed path that @@ -4126,6 +4254,34 @@ \newlet\hatch\xhatch % \end{macrocode} % +% \DescribeMacro{\gradient} +% The \cs{gradient} command approximates a linear gradient fill using +% adjacent strips of different colors. It takes one mandatory argument +% containing three items separated by commas. The first is a +% \mfc{vardef}-ed function that produces the colors, the second is the +% thickness of the color strips and the third is the angle these strips +% make with the horizontal. +% +% \DescribeMacro{\areagradient} +% This allows more general shading. It produces a fill consisting of +% differently colored ``pixels''. It also takes one mandatory argument +% containing three items separated by commas. The first is a +% function of two variables that produces the colors, the second is the +% width of the pixels and the third is their height. +% +% \DescribeMacro{\radialgradient} +% This allows shading in a concentric circular pattern. It produces a fill +% consisting of differently colored circular strips. It also takes one +% mandatory argument containing three items separated by commas. The first +% is a function of one variable that produces the colors, the second is +% the thickness of the circular strips, and the third is an ordered pair +% (the center the circles). +% \begin{macrocode} + \newdef\gradient{\mfp@rendi{axialgradient}}% + \newdef\areagradient{\mfp@rendi{areagradient}}% + \newdef\radialgradient{\mfp@rendi{radialgradient}}% +% \end{macrocode} +% % \DescribeMacro{\gfill} % \cs{gfill} take one optional argument, the color with which to fill. % Under \MF{} the color must be a numeric (representing a level of gray) @@ -4145,6 +4301,7 @@ \newdef\gclip{\mfp@rendmac{Clip}}% % \end{macrocode} % +% % \subsubsection{Modifying a curve}\label{transforming} % % The following are transformation prefixes. They are all (except @@ -4160,6 +4317,7 @@ % do not compensate and users don't seem to mind. % \begin{itemize} % \item \cs{reverse} and \cs{xyswappath} have no argument. +% \item \cs{reversepath} = \cs{reverse}. % \item \cs{rotatepath} takes \marg{\meta{point},\meta{angle}}. % \item \cs{shiftpath} takes \marg{\meta{pair}}. % \item \cs{scalepath} takes \marg{\meta{center of scaling},\meta{factor}}. @@ -4176,7 +4334,7 @@ % % All of them simply write the \grafbase{} command of nearly the same % name, with the same arguments, via -% \cs{mfp@modi}.\SpecialUsageIndex{\reverse} +% \cs{mfp@modi}.\SpecialUsageIndex{\reversepath}\SpecialUsageIndex{\reverse} % \SpecialUsageIndex{\xyswappath}\SpecialUsageIndex{\rotatepath} % \SpecialUsageIndex{\shiftpath}\SpecialUsageIndex{\scalepath} % \SpecialUsageIndex{\xscalepath}\SpecialUsageIndex{\yscalepath} @@ -4185,15 +4343,16 @@ % \SpecialUsageIndex{\transformpath} % % \begin{macrocode} - \newdef\reverse{\mfp@addmac{reverse}}% + \newdef\reversepath{\mfp@addmac{reverse}}% + \newlet\reverse\reversepath \newdef\xyswappath{\mfp@modmac{xyswappedpath}}% \newdef\rotatepath{\mfp@modi{rotatedpath}}% \newdef\shiftpath{\mfp@modi{shiftedpath}}% \newdef\scalepath{\mfp@modi{scaledpath}}% \newdef\xscalepath{\mfp@modi{xscaledpath}}% \newdef\yscalepath{\mfp@modi{yscaledpath}}% - \newdef\slantpath{\mfp@modi{xslantedpath}}% - \newlet\xslantpath\slantpath + \newdef\xslantpath{\mfp@modi{xslantedpath}}% + \newlet\slantpath\xslantpath \newdef\yslantpath{\mfp@modi{yslantedpath}}% \newdef\reflectpath{\mfp@modi{reflectedpath}}% \newdef\transformpath{\mfp@modi{transformedpath}}% @@ -4240,6 +4399,19 @@ \newdef\randomlines{\mfp@modi{randomlines}}% % \end{macrocode} % +% \DescribeMacro{\interpolatepath} +% This prefix macro has one mandatory argument containing a number and a path, +% separated by a comma. The number can be any \MF{} numeric expression and +% the path can be any \MF{} path expression. The number should normally be +% in the range $0$ to $1$ and the path normally a variable (e.g, defined using +% \cs{store}). It returns a path which is between the one in its argument +% and the one that follows. If the number is $0$, the following path is +% returned unchanged, if the number is $1$ the path in the argument is +% returned. +% \begin{macrocode} + \newdef\interpolatepath{\mfp@modi{interpolatedpath}}% +% \end{macrocode} +% % \DescribeMacro{\arccomplement} % This can precede an arc and then returns its complement. It starts at % the last point of the following arc and ends at the beginning of that @@ -4251,6 +4423,7 @@ \newdef\arccomplement{\mfp@modmac{arccomplement}}% % \end{macrocode} % +% % \subsubsection{Adding arrowheads (and tails)}\label{arrows} % % Paths can now have heads and tails and something placed in the @@ -4333,6 +4506,7 @@ % % This ends the prefix macros. % +% % \subsection{Transforming the coordinate system}\label{coordinate} % % \DescribeMacro{\coords} @@ -4382,6 +4556,7 @@ \newdef\xyswap{\applyT{xyswap}}% % \end{macrocode} % +% % \subsection{Axes and grids}\label{axes} % % An axis would normally not be thought of as a figure macro, because one @@ -4468,7 +4643,7 @@ % first argument (that is, the expectation that optional arguments come % first is still satisfied). The optional argument is the length of the % marks. The position of the marks is controlled separately by the -% \cs{setaxismarks} command, described in section~\ref{othersettings}. +% \cs{setaxismarks} command, described in subsection~\ref{othersettings}. % \begin{macrocode} \newdef\axismarks##1{\mfp@defaultopt{\mfp@marks{##1}}{\the\hashlen}}% \newdef\xmarks{\axismarks x}% @@ -4505,7 +4680,7 @@ % \DescribeMacro{\vgridlines} % \cs{vgridlines} is the vertical version. % -% No arguments are shown because \cs{mfp@simple} or \cs{mfp@simpli} will +% No arguments are shown because \cs{mfp@simple} or \cs{mfp@simplei} will % read what it needs. % \begin{macrocode} \def\grid{\mfp@defaultopt{\mfp@simplei{vargrid}}{\the\griddotsize}}% @@ -4570,6 +4745,7 @@ \mfp@defaultopt{\mfp@vectorfield{plr}}{\the\headlen}}% % \end{macrocode} % +% % \subsection{Visualizing points}\label{points} % % \DescribeMacro{\point} @@ -4611,6 +4787,7 @@ \mfp@defaultopt\mfp@plottext{cc}}% % \end{macrocode} % +% % \subsection{Some composite objects}\label{composite} % % \DescribeMacro{\tile} @@ -4676,10 +4853,10 @@ \mfp@checklatexenv{connect}{\aftergroup\@mfpstarttrue}{}}% % \end{macrocode} % +% % \subsection{Other graphical features}\label{otherfeatures} % -% And now for something completely different: pie charts and bar charts -% (or bar graphs, or histograms). +% And now for something completely different. % % \DescribeMacro{\piechart} % Actually, nothing is drawn by the \cs{piechart} command; it only defines @@ -4768,7 +4945,7 @@ % members of the just mentioned array). It is a figure macro and take the % number of the bar as its mandatory argument. Aliases \cs{graphbar}, % \cs{histobar} and \cs{ganttbar} are provided. We avoid \cs{bar} because -% it is already a math accent command. This ends \cs{mfp@grafmacs}. +% it is already a math accent command. % \begin{macrocode} \newlet\barchart\mfpbarchart \newlet\bargraph\barchart @@ -4778,19 +4955,33 @@ \newlet\graphbar\chartbar \newlet\histobar\chartbar \newlet\ganttbar\chartbar +% \end{macrocode} +% +% \DescribeMacro{\gbrace} +% Finally, a command to create a brace shape with given ends and a given +% location for the cusp. We name it with a `g' so as not to overwrite a +% possible text command with a similar name. The argument is simply passed +% to the corresponding \grafbase{} command; it consists of three points +% separated by commas denoting, respectively, the start of the brace, +% the cusp, and the end. Distance from cusp to line connecting start and +% end must be less than about 3/4 the distance to either start or end. +% +% This ends \cs{mfp@grafmacs}. +% \begin{macrocode} + \newdef\gbrace##1{\mfp@figmac{mkbrace(##1)}}% }% end \mfp@grafmacs % \end{macrocode} -%\toks0={^^A What's this? +%\toks0={^^A What's this all about? \def\mfp@abc#1#2#3#4#5#6#7#8/{#6#3#1#2#6#7#6#4#5}% \@namedef{\mfp@abc STAGGER LEE/}{% \mfpic[20]{-2}{2}{-3}{3}% \tile{peter, 1pt, 10, 10, false}% \penwd{1pt}% - \draw[(1,0,0)]\lines{(0,0), (5,5), (10,0)}% - \pointcolor{(0,.8,0)}% + \draw[rgb(1,0,0)]\lines{(0,0), (5,5), (10,0)}% + \pointcolor{rgb(0,.8,0)}% \point[3pt]{(2.5,7.5)}% \endtile - \draw\tess{peter}\gfill[(1,1,0)]\ellipse{(0,0),2,3}% + \draw\tess{peter}\gfill[rgb(1,1,0)]\ellipse{(0,0),2,3}% \endmfpic}% %} % @@ -4807,6 +4998,8 @@ \newlet\mfpgantt\mfpbarchart % \end{macrocode} % +% +% % \section{Implementing the graphics macros} % % To keep \cs{mfp@grafmacs} from becoming unweildy, we define here all the @@ -4845,8 +5038,15 @@ \newdef\mfp@pshcircle#1#2{\mfp@figmac{pshcircle (#1, #2)}}% % \end{macrocode} % -% \cs{mfp@curve} is called by six graphics macros: \cs{curve}, -% \cs{ccurve}, \cs{mfbezier} and their closed variants . Its two arguments +% The first argument of \cs{mfp@hypergeodesic} is a string that sets the +% context: \texttt{UD} for the unit disk, \texttt{UHP} for the upper +% half-plane. The second argument should be the two points to join. +% \begin{macrocode} +\newdef\mfp@hypergeodesic#1#2{\mfp@figmac{#1geodesic (#2)}}% +% \end{macrocode} +% +% Six graphics macros call \cs{mfp@curve}: \cs{curve}, +% \cs{convexcurve}, \cs{mfbezier} and their closed variants . Its two arguments % are the name of a \grafbase{} command, and \mfc{true} or \mfc{false}. % This works for any \grafbase{} command that creates a smooth path from a % list of points, provided the command has two versions: one that begins @@ -5150,7 +5350,7 @@ % the first argument of \cs{mfp@axis} is empty rather than a default. % % We use \cs{mfp@getaxis} to check the mandatory argument and return the -% default head length in \cs{mfp@defheadlen}. It also stores the +% default head length in \cs{mfp@defaultheadlen}. It also stores the % letter in \cs{mfp@axisletter}, but returns `\texttt{x}' for an invalid % one. % @@ -5163,9 +5363,10 @@ % would produce. This is slightly more efficient than calling \cs{arrow}. % \begin{macrocode} \newdef\mfp@axis#1#2{\mfp@getaxis#2{(none)}\mfp@end\axis - \mfp@addmac{headpath (\mfp@emptysub{#1}{\mfp@defheadlen}, 0, 0)}% + \mfp@addmac{headpath (\mfp@emptysub{#1}{\mfp@defaultheadlen}, 0, 0)}% \axisline{\mfp@axisletter}}% -\newdef\mfp@doaxes#1#2{\def\mfp@@axis##1{\mfp@axis{#1}{##1}\mfp@@doaxis}% +\newdef\mfp@doaxes#1#2{% + \def\mfp@@axis##1{\mfp@axis{#1}{##1}\mfp@@doaxis}% \mfp@@doaxis#2\mfp@end}% \newdef\mfp@@doaxis{\mfp@ifend{}\mfp@@axis}% % \end{macrocode} @@ -5187,7 +5388,6 @@ \newdef\mfp@vectorfield#1#2#3#4#5{% \mfcmd{#1vectorfield (#2, #3) (#4) (#5)}}% % \end{macrocode} -% % The first argument of both these is the optional size argument of the % calling commands (\cs{point} and \cs{plotsymbol}). For % \cs{mfp@plotsymbol} the second argument is the symbol name. @@ -5234,8 +5434,10 @@ % \end{macrocode} % % +% % \section{The \env{mfpic} environment}\label{mfpicenv} % +% % \subsection{Initializing the environment}\label{mfpicinitializations} % % For mostly historical reasons, the macros that create labels are @@ -5367,6 +5569,7 @@ \@graphbot 0pt % \end{macrocode} % +% % \subsection{Initializing the \MF{} picture} % \label{current} % @@ -5377,8 +5580,7 @@ % figure as its only argument. For debugging purposes we write a \MF{} % comment the contains the line number in the \TeX{} source file where the % \cs{mfpic} command occurred. We also write a line of dashes -% (\cs{mfp@d}) to make it easier to find the start of the environment. This -% may be removed in the public release. +% (\cs{mfp@d}) to make it easier to find the start of the environment. % % When \opt{mplabels} is in effect we need to set the font for the labels % to the saved \cs{@tcurr} by writing some \mfc{verbatimtex} code. Since @@ -5396,10 +5598,11 @@ beginmfpic(\number\mfp@count); \mfp@p\space\mfp@lineno. \mfp@ifmpost {\@nl verbatimtex \relax - \bgroup\font\noexpand\MFPcfont=\fontname\@tcurr\relax + \MFPbegingroup\font\noexpand\MFPcfont=\fontname\@tcurr\relax etex;}{}}% % \end{macrocode} % +% % \subsection{Placing text labels}\label{textlabels} % % All the rest of \cs{@mfpic} defines commands that in some way or another @@ -5467,6 +5670,7 @@ \mfp@restoreOL}% % \end{macrocode} % +% % \subsection{Surrounding the label with a path}\label{surrounding} % % These next macros place labels, but also define a path surrounding the @@ -5531,6 +5735,7 @@ \mfp@iftoken*{\tlabelellipse*[1]}{\tlabelellipse[1]}}% % \end{macrocode} % +% % \subsection{Placing multiple text labels}\label{multiple} % % One of the more onerous things about labels in \env{mfpic} environments @@ -5568,6 +5773,7 @@ \newlet\axislabels\mfp@axislabels % \end{macrocode} % +% % \subsection{Captions}\label{captions} % % Captions are not added immediately by the \cs{tcaption} command. That @@ -5590,6 +5796,8 @@ \every@mfpic}% End of \@mfpic % \end{macrocode} % +% +% % \section{Implementing the label and caption macros} % % \cs{mfp@setconv} uses the stored arguments of the surrounding @@ -5608,11 +5816,13 @@ % \begin{macrocode} \newdef\mfp@setconv{% \def\@xconv##1##2{% ##1 = coord. ##2 = dimension register or fdim - {\mfp@scratch=##1\@mfpicunit \advance\mfp@scratch by -\xmin\@mfpicunit + {\mfp@scratch=##1\@mfpicunit + \advance\mfp@scratch by -\xmin\@mfpicunit \mfp@scratch=\xfactor\mfp@scratch \global ##2=\mfp@scratch}}% \def\@yconv##1##2{% ditto - {\mfp@scratch=##1\@mfpicunit \advance\mfp@scratch by -\ymin\@mfpicunit + {\mfp@scratch=##1\@mfpicunit + \advance\mfp@scratch by -\ymin\@mfpicunit \mfp@scratch=\yfactor\mfp@scratch \global ##2=\mfp@scratch}}}% \newdef\mfp@inittlabels{% @@ -5787,11 +5997,11 @@ % \begin{macrocode} \@yconv{#2}\mfp@scratch \begingroup - \ifcase\tl@vpos \advance\mfp@scratch \tb@totalht % bottom - \advance\mfp@scratch \tlabel@sep - \or \advance\mfp@scratch 0.5\tb@totalht % center - \or \advance\mfp@scratch -\tlabel@sep % top - \else \advance\mfp@scratch \tb@ht % baseline (default) + \ifcase\tl@vpos \advance\mfp@scratch \tb@totalht + \advance\mfp@scratch \tlabel@sep % bottom + \or \advance\mfp@scratch 0.5\tb@totalht % center + \or \advance\mfp@scratch -\tlabel@sep % top + \else \advance\mfp@scratch \tb@ht % baseline (default) \fi \advance\mfp@scratch \tlabel@vadj \ifdim \mfp@scratch>\@tlabelstop @@ -5805,10 +6015,10 @@ % \begin{macrocode} \begingroup \ifcase\tl@vpos \advance\mfp@scratch \tlabel@sep % bottom - \or \advance\mfp@scratch -0.5\tb@totalht % center - \or \advance\mfp@scratch -\tb@totalht % top - \advance\mfp@scratch -\tlabel@sep - \else \advance\mfp@scratch -\tb@dp % baseline (default) + \or \advance\mfp@scratch -0.5\tb@totalht % center + \or \advance\mfp@scratch -\tb@totalht + \advance\mfp@scratch -\tlabel@sep % top + \else \advance\mfp@scratch -\tb@dp % baseline (default) \fi \advance\mfp@scratch \tlabel@vadj \ifdim \mfp@scratch<\@tlabelsbot @@ -6057,6 +6267,8 @@ #1\mfp@scratch}% % \end{macrocode} % +% +% % \section{Placing the picture: \cs{endmfpic}}\label{endmfpic} % % \DescribeMacro{\endmfpic} @@ -6072,7 +6284,7 @@ \mfp@DBlog{Definition of closure of mfpic environment.}% \newdef\endmfpic{\every@endmfpic \mfsrc{% - \mfp@ifmpost{\@nl verbatimtex \relax\egroup\space etex;}{}\@nl + \mfp@ifmpost{\@nl verbatimtex \relax\MFPendgroup\space etex;}{}\@nl endmfpic; \mfp@p\space(\number\mfp@count) \mfp@lineno.\@nl \mfp@p\mfp@d\mfp@d\mfp@d\@nl}% \ifmfpicdebug\wlog{}\wlog{Mfpic: ENTERED endmfpic.}\wlog{}\fi @@ -6084,6 +6296,7 @@ \ifmfp@noship \else % \end{macrocode} % +% % \subsection{Loading and measuring the graphic}\label{loading} % % Now we load the graphic. It would be at this point that we could add a @@ -6167,6 +6380,7 @@ \fi % \end{macrocode} % +% % \subsection{Adding labels and caption}\label{addlabel} % % We now add the boxes \cs{@alltlabels} and \cs{@backtext} onto the graph @@ -6192,9 +6406,11 @@ \fi \ifdim\@tlabelsleft < \maxdimen \setbox\@alltlabels\vtop to 0pt{% - \kern \mfpiclly bp \moveleft \mfpicllx bp \box\@alltlabels\vss}% + \kern \mfpiclly bp + \moveleft \mfpicllx bp \box\@alltlabels\vss}% \setbox\@backtext \vtop to 0pt{% - \kern \mfpiclly bp \moveleft \mfpicllx bp \box\@backtext \vss}% + \kern \mfpiclly bp + \moveleft \mfpicllx bp \box\@backtext \vss}% % \end{macrocode} % Then we adjust \cs{@tlabelsleft}, etc. for the boundingbox offset. % The graph dimensions are also adjusted if the tlabel dimensions extend @@ -6272,6 +6488,7 @@ \global\mfpicwidth\wd\@wholegraph % \end{macrocode} % +% % \subsection{Placing the graphic}\label{placing} % % Add a frame around the box \cs{@wholegraph} in draft mode (so its size @@ -6337,8 +6554,10 @@ % \end{macrocode} % % +% % \section{Additional features}\label{additional} % +% % \subsection{Saving a copy of the picture}\label{saving} % % \DescribeMacro{\newsavepic} @@ -6385,6 +6604,7 @@ \newdef\usepic#1{\leavevmode \copy#1\relax}% % \end{macrocode} % +% % \subsection{Putting a frame around it}\label{frame} % % This is essentially code I wrote years ago to have a framing command @@ -6428,6 +6648,7 @@ \mfp@ifdefined\framed{}{\let\framed\mfpframed}% % \end{macrocode} % +% % \subsection{Adding \mfc{verbatimtex} to the \file{.mp} % file}\label{verbatimtex} % @@ -6480,6 +6701,7 @@ % \end{macrocode} % % +% % \section{Finale}\label{finale} % % Set the default starting graphic number. We used to start at 0 and @@ -6510,3 +6732,4 @@ % %\clearpage %\Finale +%\endinput diff --git a/Master/texmf-dist/source/generic/mfpic/mfpic.ins b/Master/texmf-dist/source/generic/mfpic/mfpic.ins index 4b04ba5007b..a66d2832236 100644 --- a/Master/texmf-dist/source/generic/mfpic/mfpic.ins +++ b/Master/texmf-dist/source/generic/mfpic/mfpic.ins @@ -1,5 +1,5 @@ % File: mfpic.ins -% A part of mfpic 1.06 2011/03/08 +% A part of mfpic 1.10 2012/12/03 % \input docstrip \keepsilent @@ -7,7 +7,7 @@ ------------------------------------------------------------------- -Copyright 2002--2011, Daniel H. Luecking +Copyright 2002--2012, Daniel H. Luecking Mfpic may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at @@ -30,6 +30,7 @@ endinput.^^J% \generate{\file{mfpic.tex}{\from{mfpic.dtx}{tex}} \file{mfpic.sty}{\from{mfpic.dtx}{sty}} + \file{mfpicdef.tex}{\from{mfpic.dtx}{defs}} \usepostamble\zyx \file{grafbase.mf}{\from{grafbase.dtx}{MF}} \file{grafbase.mp}{\from{grafbase.dtx}{MP}} @@ -41,9 +42,9 @@ endinput.^^J% ^^J ^^J To finish the installation: ^^J -^^J -- Copy the files mfpic.tex and mfpic.sty to a location where -\sJ TeX and LaTeX will find them. For example, in a TDS compliant -\sJ system, the directory TEXMF/tex/generic/mfpic/ . +^^J -- Copy the files mfpic.tex, mfpic.sty and mfppatch.tex to a +\sJ location where TeX and LaTeX will find them. For example, in a +\sJ TDS compliant system, the directory TEXMF/tex/generic/mfpic/ . ^^J ^^J -- Copy the file grafbase.mf to a location where Metafont \sJ will find it, for example TEXMF/metafont/mfpic/ . -- cgit v1.2.3