\documentclass[a4paper,twocolumn]{article} \usepackage{osf-txfonts,ctable,mkpic,moreverb} \usepackage[a4paper,margin=25mm]{geometry} \def\Mfpic{\textsl{mfpic}} \def\Mkpic{\textsl{mkpic}} \def\Perl{\textsl{Perl}} \newcommand{\makefigure}[1]{ \vspace{2ex} \begin{figure}[htb] \begin{center} \mbox{\quad\csname Fig#1\endcsname} \caption{#1} \label{fig:#1} \end{center} \end{figure} } \pagestyle{myheadings} \markright{Mkpic: how Perl can help \TeX} \begin{document} \title{Mkpic: how Perl can help \TeX} \author{Wybo Dekker\\wybo@dekkerdocumenten.nl} \maketitle \begin{abstract} Perl may be an easy interface to \TeX{} when it comes to repetitive tasks, like writing letters, creating reports from databases, and many more. This article shows how Perl can be used to generate many similar pictures \emph{via} the \Mfpic\ style \\[2ex] \noindent Keywords: \textit{perl, mfpic, mkpic} \end{abstract} \section{Introduction} I recently had to produce about 40 pictures for insertion into a book on elementary mathematics. I decided that the \Mfpic\ would suite most of my needs. But writing \Mfpic\ commands is not easy. Figure~\ref{fig:parabola}, for example, can be constructed using the following \Mfpic\ commands: \footnotesize \begin{verbatim} 1 \mftitle{parabola} \setlength{\mfpicunit}{1mm} \begin{mfpic}[16][5.45]{0}{4}{-6}{5} \axes 5 \hatchwd{2} \tlabel[bc](0,5.54){$y$} \tlabel[cl](4.21,0){$x$} \tlabel[tc](2,-0.18){\strut 2} \tlabel[bc](3,0.18){\strut 3} 10 \tlabel[cr](-0.07,-5){\strut -5} \tlabel[cr](-0.07,0){\strut 0} \tlabel[cr](-0.07,4){\strut 4} \rhatch\lclosed\connect \lines{(0,0),(0,4)} 15 \function{0,3,.05}{4-x*x} \lines{(3,-5),(3,0)} \endconnect \function{0,3.2,.05}{4-x*x} \dotted\arrow\lines{(3,-5),(0,-5)} 20 \dotted\arrow\lines{(3,-5),(3,0)} \tlabel[bc](3,4){\parbox[b]{60mm}{% \center $f(x)=4-x^2$}} \arrow\lines{(3,3.46),(1.7,1.1)} \tlabel[bc](2,5){\parbox[b]{60mm}{% 25 \center Area $O_1$}} \arrow\lines{(2,4.46),(1,2)} \tlabel[bc](4,2){\parbox[b]{60mm}{% \center Area $O_2$}} \arrow\lines{(4,1.46),(2.8,-2)} 30 \end{mfpic} \end{verbatim} \normalsize \makefigure{parabola} %\ctable[figure,label=fig:parabola,caption=parabola]{@{}c@{}}{}{\Figparabola} As you can see, this implies a lot of typing and one has to type many nested [], \{\}, and () pairs. Also, several floating point numbers, such as those in lines 6--12, depend on the scaling factors defined in line 3. They have to be calculated manually, and changing the scale will imply recalculation of those values. The scale itself is set in line 3: I wanted the picture to be 64 mm wide, so I had to calculate $64/(4-0)=16$ for the scaling factor in the x-direction. It would be much easier if one could type something like: \footnotesize \begin{verbatim} 1 begin parabola 64 64 0 -6 4 5 $x$ $y$ xmark 2 Xmark 3 ymark -5 0 4 5 bhat lines 0 0 0 4 func 0 3 .05 4-x*x lines 3 -5 3 0 ehat 10 func 0 3.2 .05 4-x*x xydrop 3 -5 arrow 3 4 1.7 1.1 $f(x)=4-x^2$ arrow 2 5 1 2 Area $O_1$ arrow 4 2 2.8 -2 Area $O_2$ 15 end \end{verbatim} \normalsize Here we see no brackets, braces or parentheses anymore, width and height are set straightforwardly to 64 mm and the labels along the axes are redefined as xmarks and ymarks, for which nothing has to be given but the x- and y-values, respectively. The corresponding y- and x-values are supposed to be calculated automatically. Another construction that frequently occurs in my pictures is a label with an arrow starting from the center of its baseline, such as the one in lines 21--23 in the long listing. This is replaced in the short listing with line 12, where the starting position of the arrow is supposed to be calculated automatically. As a result, if I want to move the label, the arrow is moved with it automatically. All this is possible by using a \Perl\ interface that converts the short command file into an \Mfpic\ source file. \section{The Perl interface} In the \Perl{} script \Mkpic{}, the available commands are all defined in the subroutine \verb|parse_input|. My initial version defined only a few commands, and while using the script, new commands were inserted when they were needed. It's easy to insert your own new commands here, just look at what's already there and create new commands by analogy. The \verb|__DATA__| section of the script contains the picture needed for this documentation (and some more). The first was the \textsl{begin} command, of course, which has also the most complex definition, as it defines many scale-dependent variables and \TeX{} commands that might be useful for any command defined later. \subsection{How to use mkpic} First of all, read the manpage of the \Perl-script, generated from the script using pod2latex, which is shown in section~\ref{manpage}. The easiest way to use the script is to append your own commands to the \verb|__DATA__| section of the script, maybe after removing what's already there, and run it. This will produce a file mkpic.sty, which provides \LaTeX-commands named \verb|\Fig|, where \verb|| stands for every name you use in the \textsl{begin} command. Finally, you can use those \verb|\Fig| commands in a \LaTeX{} document. \section{Some more examples} Here are a few more examples illustrating some features of the \Mkpic{} script: The following commands will produce figure~\ref{fig:droparrows}: \footnotesize \begin{verbatim} 1 begin droparrows 64 64 0 3 12 8 $x$ $y$ xmark $a$ 2 $x_1$ 4 $x_2$ 8 $b$ 10 ydrop 2 4.414 ydrop 4 5 5 ydrop 8 5.828 ydrop 10 6.162 label cc 4 4 $f(x_1)$ label cc 8 4 $f(x_2)$ label cc 7 8 $f(x)$ increases on $[a,b]$ 10 label cc 7 7.5 $x_10$ label tl 5 4 $f^\prime(x)$ decreasing end \end{verbatim} \normalsize \makefigure{asymptotes} Figure~\ref{fig:inflections} is produced by: \footnotesize \begin{verbatim} 1 begin inflections 64 64 -.85 -1.5 1.5 5 $x$ $y$ func -.6 1.5 .05 6*(x**4)-8*(x**3)+1 lines -.2 1 .2 1 label cr -.25 1 horizontal 5 arrow .5 2 0 1 inflection point arrow .8 1 .65 0 inflection point arrow 1 5 1.5 4.375 $f(x)=6x^4-8x^3+1$ Xmark 1 ymark \raisebox{-3.5mm}{0} 0 -1 10 xydrop 1 -1 end \end{verbatim} \normalsize \makefigure{inflections} And here is an elaborate quasi 3D picture. It shows how comments can be inserted. Standard axes are suppressed because they need special treatment (see figure~\ref{fig:paraboloid}): \footnotesize \begin{verbatim} 1 begin paraboloid 64 64 -4 -4 4 4 - - \dashed lines -4 0 0 0 0 0 0 -4 # neg z and neg y \dashed 5 lines 0 0 3 1.73 # neg x \arrow lines 0 0 0 4 # pos y \arrow[5] lines 0 0 4 0 # pos z 10 \arrow[5] lines 0 0 -3 -1.73 # pos x \dotted lines -1 4 -1 0 -4 -1.73 # intersections y=-1 plane \dotted 15 lines -1 -.577 -4 -.577 # intersection x=2 plane with xy-plane % extra helplines \dotted lines -2 .423 -2 -.577 0 0 0 1 -2 .423 Ymark 3 20 % end of extras \dotted lines 0 3 -1 3 -4 1.27 \dashed\sclosed curve -3 2.42 -1.5 2.711 -1 2.42 -2.5 2.134 25 label bc 0 \yhi $z$ label cl \xhi 0 $y$ label tr -3.1 -1.8 $x$ label cl -.85 -.577 2 label tc 0 5.5 $f(x,y)=x^2-4x+2y^2+4y+7$ 30 xmark -1 Ymark 1 \shift{(-2,.42)} \dashed func 0 .5 .1 9*x*x 35 func -.5 0 .1 7*x*x \dashed func -1 0 .1 2*x*x func 0 1 .1 2*x*x end \end{verbatim} \normalsize \vspace*{3ex} \makefigure{paraboloid} \setcounter{secnumdepth}{1} \onecolumn \newpage \section{The mkpic manpage\label{manpage}} \small \subsection{mkpic - interface for making pictures with mfpic} \subsection{Synopsis\label{SYNOPSIS}\index{SYNOPSIS}} mkpic [options] [picfile] options: \begin{verbatim} --clean remove all but input file and die --pdfsample create pdf file with sample images --font= set default font for labels --[no]box produce framed boxes --version report version number and die --help display help info and die --[no]debug display debugging information --log= file for warning messages \end{verbatim} commands: \begin{verbatim} begin name xl yl xmin ymin xmax ymax xlabel ylabel end stop = # comment \end{verbatim} \begin{verbatim} arccst xcenter ycenter xstart ystart theta arcset xstart ystart xend yend theta arccrtt xcenter ycenter radius theta1 theta2 arc3 x1 y1 x2 y2 x3 y3 \end{verbatim} \begin{verbatim} xmark [label1] x1 [label2] x2 ... Xmark [label1] x1 [label2] x2 ... ymark [label1] y1 [label2] y2 ... Ymark [label1] y1 [label2] y2 ... \end{verbatim} \begin{verbatim} xdrop x y ydrop x y xydrop x y \end{verbatim} \begin{verbatim} arrow x1 y1 x2 y2 label label YX x y label xlabels YX x y dx label ... ylabels YX x y dy label ... \end{verbatim} \begin{verbatim} point x1 y1 x2 y2 ... dpoint x1 y1 dx1 dy1 ... lines x1 y1 x2 y2 ... dlines x1 y1 dx1 dy1 ... curve x1 y1 x2 y2 ... dcurve x1 y1 dx1 dy1 ... \end{verbatim} \begin{verbatim} rect x1 y1 x2 y2 drect x y dx dy dcrect x y dx dy crect x1 y1 x2 y2 arect xc yc width height theta bar x xdev height \end{verbatim} \begin{verbatim} func xmin xmax step expression-in-x \end{verbatim} \begin{verbatim} grid dx dy xgap ygap hatch bhat ehat \end{verbatim} \subsection{Description\label{DESCRIPTION}\index{DESCRIPTION}} \textbf{mkpic} provides an easy interface for making small pictures with mfpic. To this end you create an input file has to be created consisting of commands, one per line, with space separated parameters (or you modify the \texttt{\_\_DATA\_\_} section of the \textbf{mkpic} script, which is used if you run it without an input file). \textbf{mkpic} produces two files. Assuming an input file named \emph{picfile} defaulting to \emph{mkpic} these are: \begin{description} \item[{\emph{picfile.mac}}] a macro file which will contain \textbf{TeX} commands for every picture \item[{\emph{picfile.sty}}] a style file for latex, defining the same \textbf{TeX} commands for every picture. \end{description} With the \textbf{--pdfsample} option, two other files are produced: \begin{description} \item[{\emph{picfile.pdf}}] a PDF file containing all pictures. This lets you easily check the results of your designs. \item[{\emph{picfile.tex}}] the \textbf{TeX} source used for creating this PDF file. \end{description} In \textbf{LaTeX}, you have to include \texttt{$\backslash$usepackage\{picfile\}} and to include commands like \texttt{$\backslash$Fig$<$name$>$} in your source, where \texttt{name} is the name you gave one of your pictures in an \textbf{mkpic} \texttt{begin} command. In \textbf{TeX} and \textbf{ConTeXt}, you have to \texttt{$\backslash$input} \emph{picfile.mac} and to include commands like \texttt{$\backslash$Fig$<$name$>$} in your source, where \texttt{name} is the name you gave one of your pictures in an \textbf{mkpic} \texttt{begin} command. In \textbf{TeX}, you must use the \texttt{$\backslash$bye} command (\textbf{not} \texttt{$\backslash$end} to finish your \textbf{TeX} source See the RUNNING section for how to run \textbf{mkpic} and \textbf{TeX}/\textbf{LaTeX}/\textbf{ConTeXt}. \subsection{COMMANDS\label{COMMANDS}\index{COMMANDS}} The source is set up so that it is easy to add your own commands, Currently the following commands have been implemented: \begin{description} \item[{\textbf{begin end}}] Every picture begins with the \textbf{begin} command and ends with the \textbf{end} command. The \textbf{begin} command defines a name for the picture and defines a tex command with that name, prefixed with 'Fig'. The resulting command is written to a \emph{.mac} file. Thus the command \begin{verbatim} begin aa ... \end{verbatim} starts writing \texttt{$\backslash$def$\backslash$Figaa\{...} to the \emph{.mac} file, and the picture can be reproduced in a \textbf{TeX} document by importing the \emph{.mac} file and using the \texttt{$\backslash$Figaa} command. xl and yl are the lengths of the x- and y-axes. xlabel and ylabel are the label that are placed at the ends of those axes. Use a space to suppress labeling, or "-" to suppress drawing the axes at all. \item[{\textbf{stop}}] stops further reading of the input. Useful if you have many pictures, but want to see only the first few for testing purposes. \item[{\textbf{var=value}}] sets the variable var to value. This variable, or an expression containing it, can be used instead of any numerical parameter. Variable names may contain lower and uppercase letters, digits or underscores, with the restriction that they must start with a letter and may not end in an underscore. \item[{\#}] denotes a comment \item[{\textbf{xmark ymark Xmark Ymark}}] These commands place one or more labels along the x- or y-axes, either below (\textbf{xmark} and \textbf{ymark}) of above (\textbf{Xmark} and \textbf{Ymark}) the axis. For the \textbf{[xXyY]mark} commands a parameter containing any character other than [-.0-9] is interpreted as the label (this implies that you cannot use expressions here!) to be placed and its position is expected in the next parameter. If a parameter is just a number, it is placed at that x-position. If you want a number to be interpreted as a label, put it in braces: \textit{\{1950\}}. \item[{\textbf{arccst}}] (Mnemonic: \textbf{c}enter \textbf{s}tart \textbf{t}heta.) Draws an arc with its center in \textit{xcenter,ycenter}, starting in \textit{xstart,ystart} and with an arc length of \textit{theta} degrees. \item[{\textbf{arcset}}] (Mnemonic: \textbf{s}tart \textbf{e}nd \textbf{t}heta.) Draws an arc starting in \textit{xstart,ystart}end ending in \textit{xend,yend} and with an arc length of \textit{theta} degrees. \item[{\textbf{arccrtt}}] (Mnemonic: \textbf{c}enter \textbf{r}adius \textbf{t}heta1 \textbf{t}heta2.) Draws an arc with its center in \textit{xcenter,ycenter}, a radius \textit{radius} starting at \textit{theta1} degrees ænd ending at \textit{theta2} degrees. \item[{\textbf{arc3}}] (Mnemonic: \textbf{3} points.) Draws an arc starting at \textit{(x1,y1), through (x2,y2) and ending in (x3,y3)}. \item[{\textbf{xdrop ydrop xydrop}}] These commands draw dotted arrows perpendicularly to the x-axis, the y-axis and both axes, respectively, ending on the axes with the arrow head. \item[{\textbf{arrow}}] draws an arrow from \textit{(x1,y1)} to \textit{(x2,y2)} labeled on its tail with \textit{label} \item[{\textbf{label}}] draws a label at \textit{(x,y)}. \textit{YX} tells how it will be adjusted: for Y=t,b,c \textit{(x,y)} will be, in the y-direction, on top, bottom or center of the label respectively, for X=l,r,c it will be, in the x-direction, left, right or center adjusted on \textit{(x,y)}. Thus \begin{verbatim} label tl 0 0 Hello World! \end{verbatim} will draw the string "Hello World" with its lower left corner at (0,0) \item[{\textbf{xlabels}}] draws many labels, starting at \textit{(x,y)}, and incrementing \textit{x} with \textit{dx} after every label. \textit{YX}: see \textbf{label}. Labels may not contain spaces; if you need spaces, use \texttt{\~{}} instead. \item[{\textbf{ylabels}}] Same as \textbf{xlabels}, but incrementing \textit{y} with \textit{dy} instead. \item[{\textbf{point}}] draws points (dots) at \textit{(x1,y1)}, \textit{(x2,y2)} et cetera. \item[{\textbf{dpoint}}] draws points (dots) starting at \textit{(x1,y1)} and then moving by \textit{(dx1,dy1)}, \textit{(dx2,dy2)} et cetera. \item[{\textbf{lines}}] draws line segments from \textit{(x1,y1)} to \textit{(x2,y2)}, \textit{(x3,y3)} et cetera. \item[{\textbf{dlines}}] draws line segments starting at \textit{(x1,y1)} and then moving by \textit{(dx1,dy1)}, \textit{(dx2,dy2)} et cetera. \item[{\textbf{curve}}] draws a bezier curve from \textit{(x1,y1)} to \textit{(x2,y2)}, \textit{(x3,y3)} et cetera. \item[{\textbf{dcurve}}] draws a bezier curve starting at \textit{(x1,y1)} and then moving by \textit{(dx1,dy1)}, \textit{(dx2,dy2)} et cetera. \item[{\textbf{rect}}] draws a rectangle with diagonal points at \textit{(x1,y1)} and \textit{(x2,y2)}. \item[{\textbf{drect}}] draws a rectangle with diagonal points at \textit{(x,y)} and \textit{(x+dx,y+dy)}. \item[{\textbf{crect}}] clears a rectangle with diagonal points at \textit{(x1,y1)} and \textit{(x2,y2)}. \item[{\textbf{dcrect}}] clears a rectangle with diagonal points at \textit{(x,y)} and \textit{(x+dx,y+dy)}. \item[{\textbf{arect}}] draws a rectangle with a widdh \textit{width} and æ height \textit{height}; the middle of the bottom is at \textit{(xc,yc)} and the centerline through \textit{(xc,yc)} makes an angle \textit{theta} with the x-axis. \item[{\textbf{bar}}] draws a equivalent with \textit{rect x-xdev 0 x+xdev height} \item[{\textbf{func}}] draws the function given by \textit{expression-in-x} between \textit{xmin} and \textit{xmax}, stepping with \textit{step} units in the x-direction. Note that the \textit{expression-in-x} will be evaluated by \textbf{metafont}, so you will have to use metafont syntax. \item[{\textbf{grid}}] draw dotted grid lines at distances dx and dy in the x- and y directions; the gaps between the dots are set to \textit{xgap} an \textit{ygap} respectively. For an esthetic appearance, be sure to use integer \textit{dx/xgap} ænd \textit{dy/ygap} ratios. \item[{\textbf{hatch}}] hatch the closed curve that follows. \item[{\textbf{bhat}}] starts a path that will eventually be closed, and then hatched. \item[{\textbf{ehat}}] ends a path started with \textbf{bhat}, closes it and then hatches it. \item[{\textbf{anything else}}] will be inserted as is in the macro file, and therefore should be a valid \textit{mfpic} statement. You use this when you need such a statement only once, or a few times and therefore see no need to define a proper command for it. \end{description} \subsection{Running mkpic/TeX\label{RUNNING_mkpic_TeX}\index{RUNNING mkpic/TeX}} \subsubsection*{The difficult way\label{The_difficult_way}\index{The difficult way}} The effect of running \textbf{mkpic picfile} is the creation of \emph{picfile.mac}, which you can \texttt{$\backslash$input} into a \textbf{TeX} or \textbf{ConTeXt} source, and \emph{picfile.sty} which can be input into a \textbf{LaTeX} source using the \texttt{$\backslash$usepackage} command. After running \textbf{TeX} (or \textbf{LaTeX} or \textbf{ConTeXt}), you will find a file \emph{picfile.mf} and you will have to run \textbf{metafont} on it, which (assuming you configured \textbf{TeX} for 600 dpi) produces picfile.600gf. This file will have to be converted to a pk file with \textbf{gftopk}. Finally, you need to run \textbf{TeX} again. So the sequence is: \begin{description} \item[{\$}] mkpic picfile \item[{\$}] tex file.tex \item[{\$}] mf picfile \item[{\$}] gftopk picfile.600gf \item[{\$}] tex file \end{description} \subsubsection*{The easy way\label{The_easy_way}\index{The easy way}} You can also include this line into your \textbf{TeX} or \textbf{ConTeXt} source (before \texttt{$\backslash$input}ing picfile.mac) or into your \textbf{LaTeX} source (before \texttt{$\backslash$usepackage\{picfile\}}: \texttt{$\backslash$immediate$\backslash$write18\{mkpic picfile\}} and \textbf{TeX} (\textbf{LaTeX}, \textbf{ConTeXt}) will do everything for you, except that you will have to run \textbf{TeX} at least twice. You need, however, to 1) finish your texjob with \texttt{$\backslash$bye}, \textbf{not} \texttt{$\backslash$end}, and 2) enable the \texttt{$\backslash$write18} command by setting, in \emph{texmf.cnf}, the \texttt{shell\_escape} variable to true (\texttt{t}) (or ask your system administrator to do so). \subsection{Bug\label{BUG}\index{BUG}} Currently only up to 256 pictures can be generated. In the future this problem will probably be solved by introducing more than one font and generating tex-command names that have the font name in front. \subsection{Author\label{AUTHOR}\index{AUTHOR}} Wybo Dekker (wybo@dekkerdocumenten.nl) \end{document}