summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Master/texmf-dist/doc/metapost/bpolynomial/CHANGES7
-rw-r--r--Master/texmf-dist/doc/metapost/bpolynomial/README2
-rw-r--r--Master/texmf-dist/doc/metapost/bpolynomial/TODO4
-rw-r--r--Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.pdfbin510858 -> 217467 bytes
-rw-r--r--Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.tex489
-rw-r--r--Master/texmf-dist/doc/metapost/bpolynomial/examples.mp247
-rw-r--r--Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp307
7 files changed, 820 insertions, 236 deletions
diff --git a/Master/texmf-dist/doc/metapost/bpolynomial/CHANGES b/Master/texmf-dist/doc/metapost/bpolynomial/CHANGES
index b4bbb32273c..6b935bdab01 100644
--- a/Master/texmf-dist/doc/metapost/bpolynomial/CHANGES
+++ b/Master/texmf-dist/doc/metapost/bpolynomial/CHANGES
@@ -1,3 +1,10 @@
+Version 0.5 released on 2007-12-12:
+* New:
+ + The package can now compute paths of square and cubic roots.
+ + Added a plain interface.
+ + Improved documentation.
+
+
Version 0.4 released on 2007-11-28:
* New:
+ The package can now compute paths of derivatives and tangents.
diff --git a/Master/texmf-dist/doc/metapost/bpolynomial/README b/Master/texmf-dist/doc/metapost/bpolynomial/README
index a1715c93e44..8562f37814d 100644
--- a/Master/texmf-dist/doc/metapost/bpolynomial/README
+++ b/Master/texmf-dist/doc/metapost/bpolynomial/README
@@ -2,7 +2,7 @@
% http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
% for the details of that license.
-package: bpolynomial v0.4 2007/11/28
+package: bpolynomial v0.5 2007/12/12
author: Stephan Hennig (stephanhennig@arcor.de)
diff --git a/Master/texmf-dist/doc/metapost/bpolynomial/TODO b/Master/texmf-dist/doc/metapost/bpolynomial/TODO
index 518aa9cd596..fcfc73a6223 100644
--- a/Master/texmf-dist/doc/metapost/bpolynomial/TODO
+++ b/Master/texmf-dist/doc/metapost/bpolynomial/TODO
@@ -1,5 +1,3 @@
-* Drawing square and cubic roots and tangents thereof. Note, derivatives
- of roots cannot be represented by Bezier curves.
* Approximation of arbitrary polynomials by multi-segment Bezier curves.
-Contributions are welcome! Especially for the second item.
+Contributions are welcome!
diff --git a/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.pdf b/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.pdf
index 6caa622a1a3..42e54391067 100644
--- a/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.pdf
+++ b/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.tex b/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.tex
index e91aee36e6f..6b8141233d5 100644
--- a/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.tex
+++ b/Master/texmf-dist/doc/metapost/bpolynomial/bpolynomial.tex
@@ -9,7 +9,7 @@
\RequirePackage[resetfonts]{cmap}
\documentclass{article}
\usepackage[T1]{fontenc}
-\usepackage{lmodern}
+\usepackage{ae}
\usepackage{amsmath}
\usepackage{amssymb}
\newcommand*{\cmd}[1]{\texttt{#1}}
@@ -36,40 +36,62 @@
\fi
\begin{document}
-\title{The \pkg\ package\thanks{This document describes \pkg\ v0.4, last revised 11/28/2007.}}
+\title{The \pkg\ package\thanks{This document describes \pkg\ v0.5, last revised 2007/12/12.}}
\author{Stephan Hennig\thanks{stephanhennig@arcor.de}}
\maketitle
\begin{abstract}
-The MetaPost package \pkg\ helps drawing polynomial functions of up to degree three. It provides macros to calculate \B\ curves exactly matching a given constant, linear, quadratic or cubic polynomial. Additionally, paths of derivatives and tangents can be calculated.
+The MetaPost package \pkg\ helps plotting polynomial and root functions. It provides macros to calculate one-segment \B\ curves exactly matching a given cubic polynomial or square or cubic root function. Additionally, tangents on all functions and derivatives of polynomials can be calculated.
\end{abstract}
+\setcounter{secnumdepth}{3}
+\setcounter{tocdepth}{2}
\begin{multicols}{2}
\tableofcontents
\end{multicols}
-\section{Introduction}
-MetaPost has a variable type \cmd{path} that can be used for drawing smooth and visualy pleasing curves. Internally, paths are \B\ curves and MetaPost is able to calculate the points along such a curve.\footnote{Since PostScript has a concept of \B\ curves, too, for MetaPost drawing a path is simply an act of copying the parameters of the corresponding \B\ curve into PostScript output. But nonetheless MetaPost \emph{can} calculate points on a \B\ curve.}
+\section{Introduction}\label{sec:intro}
+MetaPost has a variable type \cmd{path} that can be used for drawing smooth and visualy pleasing curves. When plotting graphs, the problem users are confronted with is how to define a suitable path representing a given function $f(x)$?
+
+The \name{splines} package by Dan Luecking provides macros for drawing smooth piece-wise \B\ curves through arbitrary sample points of a function.~\cite{mp:splines} Since \B\ curves are polynomials of degree three, for cubic polynomials we can do better and find a matching one-segment \B\ curve. This package eases the task of finding a \B\ curve corresponding to a given function of the following types:
+\begin{align}
+f(x) & = ax^3 + bx^2 + cx + d \\
+f(x) & = u \sqrt{x + v} + w \\
+f(x) & = u \sqrt[3]{x + v} + w
+\end{align}
-When drawing graphs, the problem users are confronted with is how to define a suitable path representing a given function $f(x)$? The \name{splines} package by Dan Luecking provides macros to draw smooth piece-wise \B\ curves through arbitrary sample points.~\cite{mp:splines} However, since \B\ curves are polynomials of degree three, we can do better with just one \B\ curve segment for such polynomials. This package eases the task of finding a \B\ curve matching a given polynomial
+\section{Usage}\label{sec:usage}
+The \pkg\ package provides two flavours of user interfaces:
+\begin{itemize}
+\item An advanced interface, that first requires a function to be defined and then provides access to the \B\ curve corresponding to the function, its tangent or derivative in a given intervall.
+\item A plain interface, that gives instant access to the \B\ curve matching a given function in an intervall.
+\end{itemize}
+The plain interface is less powerful, but might be convenient in certain circumstances. It is briefly described in section~\ref{sec:plaininterface}. The average user most likely wants to use the advanced interface, so we will discuss that first.
+
+\subsection{Plotting polynomials}\label{sec:polynomials}
+\subsubsection{Defining polynomials}\label{sec:newBPolynomial}
+As was said before, calculating the \B\ curve of a polynomial function first requires a function to be defined. The macro for defining a polynomial
\begin{equation}
-f(x) = ax^3 + bx^2 + cx + d
+ f(x) = ax^3 + bx^2 + cx + d
\end{equation}
+is called
+\begin{center}
+ \cmd{newBPolynomial}
+\end{center}
+and takes five arguments. First argument is a suffix and the remaining four arguments are the four coefficients of the polynomial function $a$, $b$, $c$, $d$.
-
-\section{Usage}
-\subsection{\cmd{newBPolynomial}}\label{sec:newBPolynomial}
-The \pkg\ package provides just one macro \cmd{newBPolynomial}. This macro takes one suffix argumant and four numeric arguments that are the coefficients of the given polynomial. A polynomial definition for a function
+A definition of a polynomial
\begin{equation}
f(x) = 2x^3 + 0x^2 - 3x - 1
\end{equation}
-exemplary looks like this
+associated with suffix \cmd{f} exemplary looks like this
\begin{listing}
newBPolynomial.f(2, 0, -3, -1);
\end{listing}
-Here, numbers $2$, $0$, $-3$, $-1$ match the coefficients of our function $f$. The suffix argument \cmd{f} serves as an identifier where some names of macros and variables, that have to be called later, are derived from. To be more precise, command
+
+The suffix argument \cmd{f} serves as an identifier for deriving names of other macros, that are defined by \cmd{newBPolynomial}. To be more precise, command
\begin{center}
\cmd{newBPolynomial.<suffix>}
\end{center}
@@ -83,69 +105,158 @@ defines three new macros
\end{center}
that do the real work. These macros are described in the following sections.
-\subsection{\cmd{<suffix>.getPath}}\suppressfloats
-Macro \cmd{<suffix>.getPath(xmin, xmax)} returns a path exactly matching the polynomial defined by \cmd{newBPolynomial.<suffix>} on an intervall $[xmin, xmax]$. Let's have a look at an example. Drawing our polynomial $f(x)$ on the intervall $(-2, 2)$ can be done with the following code (figure~\ref{fig:cubic}).
+\subsubsection{Getting the \B\ curve of a polynomial}\label{sec:getPath}
+Once a polynomial $\langle$suffix$\rangle$ is defined, the macro to request a \B\ curve matching the function on an intervall $[x_l, x_r]$ is
+\begin{center}
+ \cmd{<suffix>.getPath}
+\end{center}
+This macro takes two argument, the intervall boundaries $x_l$ and $x_r$, and returns a polynomial shaped \B\ curve corresponding to function $\langle$suffix$\rangle$. Command \cmd{<suffix>.getPath} can be called as often as required with varying intervall boundaries and always returns a path corresponding to the new intervall.
+
+Let's have a look at an example. Plotting our polynomial $f(x)$ on the intervall $(-2, 2)$ can be done with the following code (figure~\ref{fig:cubic}).
\begin{listing}
newBPolynomial.f(2, 0, -3, -1);
draw f.getPath(-2, 2) transformed T;
\end{listing}
\begin{figure}
- \begin{minipage}[t]{.45\linewidth}
+% \begin{minipage}[t]{.45\linewidth}
\centering
\includegraphics{examples.1}
\caption{A cubic polynomial.}
\label{fig:cubic}
- \end{minipage}\hfill%
- \begin{minipage}[t]{.45\linewidth}
- \centering
- \includegraphics{examples.2}
- \caption{With a labelled point.}
- \label{fig:labelled}
- \end{minipage}
+% \end{minipage}
\end{figure}
-Note, since the base unit of MetaPost is a big point (1\,bp) in most cases polynomials have to be scaled to a proper size before plotting. It is \emph{not} recommended, however, to apply scaling to the polynomial coefficients, since current MetaPost versions\footnote{At the time of writing the latest release is MetaPost v1.002.}
-can't handle large numbers very well. Instead, scaling should be applied to the path during the \cmd{draw} operation. In this manual, scaling is applied by an affine transform
+\emph{Hint:} Since the \pkg\ package never uses $\langle$suffix$\rangle$ as a complete identifier, you can use that as the name of a path variable to store the path returned by \cmd{<suffix>.getPath} for later drawing. Any other path (array) variable serves the same purpose, though.
+\begin{listing}
+ newBPolynomial.f(2, 0, -3, -1);
+ path f;
+ f := f.getPath(-2, 2);
+ draw f transformed T;
+\end{listing}
+
+Note, since the base unit of MetaPost is a big point ($1\,\text{bp}=\frac{1}{72}\,\text{in}$) in most cases functions have to be scaled to a proper size before plotting. It is \emph{not} recommended, however, to apply scaling to polynomial coefficients, since current MetaPost versions can't handle large numbers very well.%
+\footnote{At the time of writing the latest release is MetaPost v1.002.}
+Instead, scaling should be applied to paths during \cmd{draw} operations. If not stated otherwise, in this manual, scaling is applied by an affine transform
\begin{center}
\cmd{T = identity xscaled 10mm yscaled 1mm;}
\end{center}
-Once a polynomial $\langle$suffix$\rangle$ has been defined \cmd{<suffix>.getPath} can be called as often as required with varying arguments and returns a path corresponding to the requested section of polynomial $\langle$suffix$\rangle$.
+\subsubsection{Getting a tangent on a polynomial}\label{sec:getTangent}
+Another macro set up during a function definition is
+\begin{center}
+ \cmd{<suffix>.getTangent}
+\end{center}
+This macro returns a path tangent to a function $\langle$suffix$\rangle$ at a specific point. Arguments are an $x$-coordinate, where the tangent is placed, and two values $\epsilon_l$, $\epsilon_r$ that specify the neighbourhood around $x$. The tangent path then covers the intervall $[x+\epsilon_l,x+\epsilon_r]$. This syntax has been choosen to make it easy to move a tangent along a function, keeping its neighbourhood at a fixed size.
-\emph{Hint:} Since the \pkg\ package never uses $\langle$suffix$\rangle$ as a complete identifier, you can use that as the name of a path variable to store the path returned by \cmd{<suffix>.getPath} for later drawing. Any other path (array) variable serves the same purpose, though.
+As an example, the following code draws a tangent that touches $f$ at $x=-0.5$ with a neighbourhood $\epsilon = \pm 1$ (figure~\ref{fig:tangent}).%
+\footnote{Both types of arguments to \cmd{f.getTangent}---$x$ and $\epsilon$ values---have been put in separate pairs of parentheses to make the code more readable. Even if the second pair of parentheses looks like a coordinate of type \cmd{pair}---it isn't. For MetaPost this syntax is equivalent to
+ \begin{center}
+ \cmd{draw f.getTangent(-0.5, -1, 1) transformed T;}
+ \end{center}
+}
\begin{listing}
newBPolynomial.f(2, 0, -3, -1);
- path f;
- f := f.getPath(-2, 2);
- draw f transformed T;
+ draw f.getPath(-2, 2) transformed T;
+ draw f.getTangent(-0.5)(-1, 1) transformed T;
\end{listing}
-\subsection{\cmd{<suffix>.eval}}
-Macro \cmd{<suffix>.eval} can be used to evaluate polynomial $\langle$suffix$\rangle$ at a given x-coordinate. The macro takes one argument---the x-coordinate. Labelling an arbitrary point on a polynomial can be done as follows (figure~\ref{fig:labelled}).
+\begin{figure}
+ \begin{minipage}[t]{.45\linewidth}
+ \centering
+ \includegraphics{examples.2}
+ \caption{Cubic polynomial with a tangent.}
+ \label{fig:tangent}
+ \end{minipage}\hfill%
+ \begin{minipage}[t]{.45\linewidth}
+ \centering
+ \includegraphics{examples.3}
+ \caption{And a labelled point.}
+ \label{fig:labelled}
+ \end{minipage}
+\end{figure}
+
+\subsubsection{Evaluating polynomials}\label{sec:eval}
+Additionally to getting the \B\ curve or tangent of a polynomial, polynomial functions can also be evaluated numerically at a specific location. Defining a function $\langle$suffix$\rangle$ sets up a macro
+\begin{center}
+ \cmd{<suffix>.eval}
+\end{center}
+that takes as argument an $x$-coordinate and returns the function value at that location. As an example, labelling an arbitrary point on $f$ can be done as follows (figure~\ref{fig:labelled}).
\begin{listing}
+ dotlabeldiam := 2bp;
+ labeloffset := 10bp;
newBPolynomial.f(2, 0, -3, -1);
draw f.getPath(-2, 2) transformed T;
- x := 1.5;
+ x := -0.5;
show (x, f.eval(x));
- dotlabeldiam := 2bp;
- dotlabel.ulft(btex $(1.5, 1.25)$ etex, (x, f.eval(x)) transformed T);
+ draw f.getTangent(x)(-1, 1) transformed T;
+ dotlabel.top(btex $(-0.5, 0.25)$ etex, (x, f.eval(x)) transformed T);
\end{listing}
-Note, the label has been provided explicitly in this example (after reading the coordinates off the \cmd{log} file). It is also possible to attach the correct coordinates automatically with the help of the MetaPost package \name{LaTeXMP} and the \LaTeX\ package \name{numprint}. While the former helps passing dynamically generated text from MetaPost to \LaTeX, the latter can be used to format and round numbers.~\cite{latex:numprint, mp:latexmp}.
+For simplicity, the label has been provided explicitly in this example (after reading the coordinates off the \cmd{log} file). But it is also possible to attach the correct coordinates automatically with the help of the MetaPost package \name{LaTeXMP} and \LaTeX\ package \name{numprint}. While the former helps passing dynamically generated text from MetaPost to \LaTeX, the latter can be used to format and round numbers.~\cite{latex:numprint, mp:latexmp}.
+
+\subsection{Plotting square and cubic roots}\label{sec:roots}
+Two other types of functions can be described by \B\ curves: square and cubic roots%
+\footnote{The reason square and cubic roots can be expressed in terms of \B\ curves is that both are inverse functions of cubic polynomials. More information can be found in appendix~\ref{app:roots}.}%
+. The \pkg\ package provides support for square and cubic root functions of the following type
+\begin{align}
+ f_{sqr}(x) = u \sqrt{x + v} + w\label{eq:square} \\
+ f_{cub}(x) = u \sqrt[3]{x + v} + w\label{eq:cubic}
+\end{align}
+through macros
+\begin{center}
+ \begin{tabular}{l}
+ \cmd{newBSqrRoot} \\
+ \cmd{newBCubRoot} \\
+ \end{tabular}
+\end{center}
+
+These macros are similar to \cmd{newBPolynomial}. Both macros take as arguments a suffix $\langle$suffix$\rangle$ and the three parameters $u$, $v$ and $w$ of the respective function. They define three macros
+\begin{center}
+ \begin{tabular}{l}
+ \cmd{<suffix>.getPath} \\
+ \cmd{<suffix>.eval} \\
+ \cmd{<suffix>.getTangent} \\
+ \end{tabular}
+\end{center}
+that can be used the same way as for polynomial functions.
+
+There is one notable difference between polynomial and root functions. While polynomials $z^k$ are defined for all arguments $z \in \mathbb{R}$, roots $\sqrt[k]{z}$ are only defined for non-negative arguments $z \in \mathbb{R_+}$ and therefore the functions from equations~\ref{eq:square} and~\ref{eq:cubic} are only defined for
+\begin{equation}
+ x \geq -v.\label{eq:rootargument}
+\end{equation}
-\subsection{\cmd{<suffix>.getTangent}}
-Macro \cmd{<suffix>.getTangent} returns a path tangent to polynomial $\langle$suffix$\rangle$. This macro takes three numeric arguments, the coordinate $x$ where the tangent should touch polynomial $\langle$suffix$\rangle$, and two values $\epsilon_-$, $\epsilon_+$ that specify the range the tangent is drawn in. These arguments are not the range boundaries, but the neighbourhood around $x$. The range is $[x+\epsilon_-,x+\epsilon_+]$. This syntax has been choosen to make is easier to move a tangent along a polynomial, keeping the neighbourhood fixed.
+In case the arguments to macros \cmd{<suffix>.getPath}, \cmd{<suffix>.getTangent} or \cmd{<suffix>.eval} violate equation~\ref{eq:rootargument} all macros write a warning to the log file, but go on with their calculations replacing the arguments in question (or the resulting range boundaries) by $-v$.
-As an example, the following code draws a tangent that touches $f$ at $x=-1$ with a neighbourhood $\epsilon = \pm 1$ (figure~\ref{fig:tangent}).
+The following example plots two functions $s(x) = \sqrt{x}$ and $c(x) = \sqrt[3]{x}$ with a tangent on $s$ at $x=3$ (figure~\ref{fig:squareroot}).
\begin{listing}
- newBPolynomial.f(2, 0, -3, -1);
- draw f.getPath(-2, 2) transformed T;
- draw f.getTangent(-1, -1, 1) transformed T;
+ T := identity scaled 10mm;
+ newBSqrRoot.s(1,0,0);
+ newBCubRoot.c(1,0,0);
+ draw s.getPath(0,6) transformed T;
+ draw c.getPath(0,6) transformed T;
+ draw s.getTangent(3)(-2, 2) transformed T;
\end{listing}
-\subsection{Dealing with derivatives}
-Additionally to drawing polynomials, the \pkg\ package supports drawing derivatives of polynomials and tangents thereof. In section~\ref{sec:newBPolynomial} it was said macro \cmd{newBPolynomial} defines three new macros. But this is not the full story. In fact, the command
+\begin{figure}
+ \begin{minipage}[t]{.55\linewidth}
+ \centering
+ \includegraphics{examples.5}
+ \caption{Square and cubic roots with a tangent.}
+ \label{fig:squareroot}
+ \end{minipage}\hfill%
+ \begin{minipage}[t]{.4\linewidth}
+ \centering
+ \includegraphics{examples.4}
+ \caption{First derivative of a cubic polynomial with tangent.}
+ \label{fig:derivative}
+ \end{minipage}
+\end{figure}
+
+\subsection{Dealing with derivatives}\label{sec:derivatives}
+Since plotting function often involves plotting derivatives of functions, too, the \pkg\ package provides support for plotting derivatives of polynomials and tangents thereof. Unfortunately, derivatives of root functions cannot be described by \B\ curves, so those are not supported.
+
+In section~\ref{sec:newBPolynomial} it was said macro \cmd{newBPolynomial} defines three new macros. But this is not the full story. In fact, the command
\begin{center}
\cmd{newBPolynomial.<suffix>}
\end{center}
@@ -159,140 +270,159 @@ and to get a tangent on the first derivative call
\end{center}
In total these are the macros defined by \cmd{newBPolynomial.<suffix>}:
-\begin{multicols}{2}
- \centering
- \begin{tabular}{l}
+\begin{center}
+ \begin{minipage}{.77\textwidth}
+ \begin{multicols}{2}
\cmd{<suffix>.getPath} \\
\cmd{<suffix>.eval} \\
\cmd{<suffix>.getTangent} \\
\cmd{<suffix>'.getPath} \\
\cmd{<suffix>'.eval} \\
\cmd{<suffix>'.getTangent} \\
- \end{tabular}\columnbreak
-
- \begin{tabular}{l}
- \cmd{<suffix>''.getPath} \\
- \cmd{<suffix>''.eval} \\
- \cmd{<suffix>''.getTangent} \\
- \cmd{<suffix>'''.getPath} \\
- \cmd{<suffix>'''.eval} \\
- \cmd{<suffix>'''.getTangent} \\
- \end{tabular}
-\end{multicols}
+ \cmd{<suffix>'{}'.getPath} \\
+ \cmd{<suffix>'{}'.eval} \\
+ \cmd{<suffix>'{}'.getTangent} \\
+ \cmd{<suffix>'{}'{}'.getPath} \\
+ \cmd{<suffix>'{}'{}'.eval} \\
+ \cmd{<suffix>'{}'{}'.getTangent}
+ \end{multicols}
+\end{minipage}
+\end{center}
As an example, the following code draws a tangent on the first derivative of a polynomial \cmd{f} (figure~\ref{fig:derivative}).
-\begin{figure}
- \begin{minipage}[t]{.45\linewidth}
- \centering
- \includegraphics{examples.3}
- \caption{Cubic polynomial with a tangent.}
- \label{fig:tangent}
- \end{minipage}\hfill%
- \begin{minipage}[t]{.45\linewidth}
- \centering
- \includegraphics{examples.4}
- \caption{First derivative with a tangent.}
- \label{fig:derivative}
- \end{minipage}
-\end{figure}
-
\begin{listing}
newBPolynomial.f(2, 0, -3, -1);
draw f'.getPath(-2, 2) transformed T;
- draw f'.getTangent(1, -1, 1) transformed T;
+ draw f'.getTangent(-0.25)(-1, 1) transformed T;
\end{listing}
-\subsection{Accessing polynomial coefficients}
-The coefficients passed to \cmd{newBPolynomial.<suffix>} are saved in variables \cmd{<suffix>.a}, \cmd{<suffix>.b}, \cmd{<suffix>.c} and \cmd{<suffix>.d} and can be accessed by the user.
+\subsection{Accessing function parameters}\label{sec:parameters}
+The parameters passed to one of the function defining macros are saved for internal calculations. These variables can be accessed by users, too, but should not be changed.
+
+Defining a polynomial with
+\begin{center}
+ \cmd{newBPolynomial.<suffix>(<a>, <b>, <c>, <d>)}
+\end{center}
+defines variables
+\begin{center}
+ \begin{minipage}{.77\textwidth}
+ \begin{multicols}{2}
+ \cmd{<suffix>.a} \\
+ \cmd{<suffix>.b} \\
+ \cmd{<suffix>.c} \\
+ \cmd{<suffix>.d} \\
+ \cmd{<suffix>'.a} \\
+ \cmd{<suffix>'.b} \\
+ \cmd{<suffix>'.c} \\
+ \cmd{<suffix>'.d} \\
+ \cmd{<suffix>'{}'.a} \\
+ \cmd{<suffix>'{}'.b} \\
+ \cmd{<suffix>'{}'.c} \\
+ \cmd{<suffix>'{}'.d} \\
+ \cmd{<suffix>'{}'{}'.a} \\
+ \cmd{<suffix>'{}'{}'.b} \\
+ \cmd{<suffix>'{}'{}'.c} \\
+ \cmd{<suffix>'{}'{}'.d}
+ \end{multicols}
+\end{minipage}
+\end{center}
+and sets them to the value of the corresponding coefficient.
-\section{Examples}
-This section contains some more elaborate examples. The code of all examples can also be found in file \cmd{examples.mp}.
+For root functions the following variables are used:
+\begin{center}
+ \begin{tabular}{l}
+ \cmd{<suffix>.u} \\
+ \cmd{<suffix>.v} \\
+ \cmd{<suffix>.w} \\
+ \end{tabular}
+\end{center}
-In the first example a simple coordinate system is drawn manually. Then a quadratic polynomial \cmd{f} is drawn in three strokes. Two dashed strokes correspond to the positive values of \cmd{f}, a dotted stroke corresponds to negative values. Finally, a cubic polynomial \cmd{g} is plotted and a table of points is written to the console and log file (figure~\ref{fig:multistrokes}).
+Additionally, variables
+\begin{center}
+ \begin{tabular}{l}
+ \cmd{<suffix>.a} \\
+ \cmd{<suffix>.b} \\
+ \cmd{<suffix>.c} \\
+ \cmd{<suffix>.d} \\
+ \end{tabular}
+\end{center}
+contain the coefficients of the inverse polynomial function.
-\begin{figure}
- \centering
- \includegraphics{examples.5}
- \caption{Two polynomials in a coordinate system.}
- \label{fig:multistrokes}
-\end{figure}
+\subsection{The plain interface}\label{sec:plaininterface}
+The \pkg\ package provides a plain interface, too. This interface avoids the necessity to define a function prior to calculating paths, but is limited to calculating \B\ curves of explicitly given polynomials and root functions---tangents and derivatives are not supported. The plain interface consists of three macros
+\begin{center}
+ \begin{tabular}{l}
+ \cmd{getBezierFromPolynomial} \\
+ \cmd{getBezierFromSqrRoot} \\
+ \cmd{getBezierFromCubRoot} \\
+ \end{tabular}
+\end{center}
+that take as arguments the parameters of the polynomial or root function plus the range the path should cover.
+For instance, the first example could as well have been drawn with the following code
\begin{listing}
-numeric u;
-u := 0.5cm;
- %%% Draw a coordinate system.
- xmin := -5; xmax := 6;
- ymin := -5; ymax := 6;
- drawarrow ((xmin,0)--(xmax,0)) scaled u;
- drawarrow ((0,ymin)--(0,ymax)) scaled u;
- drawoptions(withpen pencircle scaled 1bp);
- %%% Define polynomial f of degree 2.
-path f[];
- newBPolynomial.f(0, 0.5, -2, 0);
- f1 := f.getPath(-2, 0);
- f2 := f.getPath(0, 4);
- f3 := f.getPath(4, 5.5);
- draw f1 scaled u dashed evenly scaled 2;
- draw f3 scaled u dashed evenly scaled 2;
- draw f2 scaled u dashed withdots
- withpen pencircle scaled 1.5bp withcolor .5white;
- %%% Define polynomial g of degree 3.
-path g;
- newBPolynomial.g(0.3, 0, -3, -1);
- g := g.getPath(-3.5, 4);
- show g;
- draw g scaled u;
- %%% Write table with some points of g to log file.
- show "Polynomial: " & decimal g.a & "x^3+" & decimal g.b
- & "x^2+" & decimal g.c & "x+" & decimal g.d;
- for x=-5 upto 5:
- show (x, g.eval(x));
- endfor
+ draw getBezierFromPolynomial(2, 0, -3, -1)(-2, 2) transformed T;
\end{listing}
-Note command \cmd{show g} that writes path~\cmd{g} to the \cmd{log} file. Inspecting that we can easily verify \cmd{g} consists of just one path segment:
-\begingroup\small
-\begin{verbatim}
-(-3.5,-3.36273)..controls (-1,16.70013) and (1.5,-22.30025)..(4,6.2002)
-\end{verbatim}
-\endgroup
+All three macros call a macro \verb+bpolynomial_getBezierFromPolynomial+ behind the scenes, that does the necessary calculations and, in fact, is the heart of this package. The mathematics behind that macro are described in appendix~\ref{app:mathematics}.
+
+
+\section{Examples}\label{sec:examples}
+This section contains some more elaborate examples. The code of all examples is copied here, so that you can easily compare it with the resulting figures. If you want to play around with the code you can also find it in file \cmd{examples.mp}, that actually contains the code of all examples in this manual.
+\emph{One additional note in advance:} While playing with figure~\ref{fig:transparency}, the author noticed a subtle rendering bug in Adobe Reader~7.0.9, that caused the graphs and the filled area not matching exactly. In print or with GSview~4.8 and Ghostscript~8.60 everything looked fine. The problem is actually unrelated to the filling, but there seem to be some numeric issues in the \B\ curve rendering algorithm of Adobe Reader. A work-around is to modifiy problematic paths, \emph{e.\,g.}, by slightly changing their plotting range.
-The next example demonstrates how \pkg\ and John Hobby's \name{graph} package\cite{mp:graph} can be used together to draw polynomials in a coordinate system. Instead of \cmd{draw} paths have just to be drawn with a \cmd{gdraw} command. The latter macro additionally clips paths to the boundaries of the coordinate system (figure~\ref{fig:graph.mp}).
+The first example demonstrates how \pkg\ and John Hobby's \name{graph} package\cite{mp:graph} can be used together to plot polynomials in a coordinate system. The \cmd{draw} command has just to be replaced by \cmd{gdraw}. The latter command additionally clips paths to the boundaries of the coordinate system (see figure~\ref{fig:graph.mp}). Finally, in this example a table of points is printed to the console and \cmd{log} file.
\begin{figure}
\centering
- \includegraphics{examples.6}
- \caption{Packages \pkg\ and \cmd{graph} interacting.}
+ \includegraphics{examples.21}
+ \caption{Packages \pkg\ and \name{graph} interacting.}
\label{fig:graph.mp}
\end{figure}
\begin{listing}
-path f,g;
+path f, g;
xmin := -7; xmax := 7;
ymin := -7; ymax := 7;
- newBPolynomial.f(0, 0.5, -2, 0);
+ %%% Define polynomials f and g.
+ newBPolynomial.f(0.3, 0, -3, -1);
f := f.getPath(xmin, xmax);
- newBPolynomial.g(0.3, 0, -3, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
g := g.getPath(xmin, xmax);
+ %%% Draw graph.
draw begingraph(10cm, 6cm);
setrange(xmin,ymin, xmax,ymax);
autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
drawoptions(withpen pencircle scaled 1bp);
- gdraw f dashed evenly scaled 2;
- gdraw g;
+ gdraw f;
+ gdraw g dashed evenly scaled 2;
drawoptions();
endgraph;
+ show f;
+ %%% Write table with some points of f to log file.
+ show "Polynomial: " & decimal f.a & "x^3 + " &
+ decimal f.b & "x^2 + " & decimal f.c & "x + " & decimal f.d;
+ for x=-5 upto 5:
+ show (x, f.eval(x));
+ endfor
\end{listing}
+Note command \cmd{show f} that writes path~\cmd{f} to the \cmd{log} file. Inspecting that we can easily verify \cmd{f} consists of just one path segment:
+\begingroup\small
+\begin{verbatim}
+(-7,-82.90105)..controls (-2.33333,108.90105) and (2.33333,-110.90105)
+ ..(7,80.90105)
+\end{verbatim}
+\endgroup
-In the last example a cubic polynomial $f$ is drawn together with its derivatives $f'$, $f''$ and $f'''$. Additionally, for all four functions the tangents are drawn at $x=2$. Admittedly, the plot is a little bit crowded. But it should only serve as an example (figure~\ref{fig:derivatives}).
+In the next example, a cubic polynomial $f$ is plotted together with its derivatives $f'$, $f''$ and $f'''$. Additionally, for all four functions the tangents are drawn at $x=2$. Admittedly, the plot is a little bit crowded. But it should only serve as an example (figure~\ref{fig:derivatives}).
\begin{figure}
\centering
- \includegraphics{examples.7}
+ \includegraphics{examples.22}
\caption{A cubic polynomial with derivatives and tangents.}
\label{fig:derivatives}
\end{figure}
@@ -313,12 +443,12 @@ In the last example a cubic polynomial $f$ is drawn together with its derivative
gdraw f'''.getPath(-5, 5) withcolor .6white;
%%% Draw tangents and mark points.
x := 2;
- drawoptions(withcolor red+.6(green+blue));
- gdraw f.getTangent(x, -2, 2);
- gdraw f'.getTangent(x, -1, 1);
- gdraw f''.getTangent(x, -2, 2);
- gdraw f'''.getTangent(x, -2, 2);
- drawoptions(withcolor blue+.6(red+green));
+ drawoptions(withcolor (1, 0.6, 0.6));
+ gdraw f.getTangent(x)(-2, 2);
+ gdraw f'.getTangent(x)(-1, 1);
+ gdraw f''.getTangent(x)(-2, 2);
+ gdraw f'''.getTangent(x)(-2, 2);
+ drawoptions(withcolor (0.6, 0.6, 1));
dotlabeldiam := 2.5bp;
gdotlabel("", (x, f.eval(x)));
gdotlabel("", (x, f'.eval(x)));
@@ -328,8 +458,79 @@ In the last example a cubic polynomial $f$ is drawn together with its derivative
endgraph;
\end{listing}
+How about some eye candy, \emph{e.\,g.}, transparency effects? In the next example the area enclosed by two functions is filled with a transparent colour (figure~\ref{fig:transparency}).
+
+Note, advanced PDF features like transparency and shadings are provided by package \name{metafun}.~\cite{mp:metafun} Figures using such features have to be converted to stand-alone PDF files with the \cmd{mptopdf} utility before including them into a \LaTeX\ document.
+
+\begin{figure}
+ \centering
+ \includegraphics{examples-23}
+ \caption{Applying a transparent fill to an area enclosed by two functions.}
+ \label{fig:transparency}
+\end{figure}
+
+\begin{listing}
+path f, g, A;
+ xmin := -3; xmax := 6;
+ ymin := -3; ymax := 6;
+ newBPolynomial.f(-0.25, 0.5, 2, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
+ f := f.getPath(-2.5, 5.5);
+ g := g.getPath(-1.5, 5.5);
+ %%% Find area between f and g.
+ A := buildcycle(g, reverse f);
+ draw begingraph(10cm, 6cm);
+ setrange(xmin,ymin, xmax,ymax);
+ autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
+ %%% Fill area with transparent colour.
+ gfill A withcolor transparent (1, .3, (1, 0.5, 0));
+ drawoptions(withpen pencircle scaled 1bp);
+ gdraw f;
+ gdraw g dashed evenly scaled 2;
+ drawoptions();
+ endgraph;
+\end{listing}
+
+As an alternative to solid fills areas can be emphasized by hatch patterns. Hatching support is provided by package \name{hatching}.~\cite{mp:hatching} Unfortunately, packages \name{graph} and \name{hatching} do not work together. Therefore, in the next example a simple coordinate system had to be drawn manually (figure~\ref{fig:hatching.mp}).
-\section{Mathematics}
+\begin{figure}
+ \centering
+ \includegraphics{examples.14}
+ \caption{Hatching an area enclosed by two functions.}
+ \label{fig:hatching.mp}
+\end{figure}
+
+\begin{listing}
+path f, g, A;
+ T := identity xscaled 10mm yscaled 6mm;
+ %%% Draw coordinate system.
+ xmin := -3; xmax := 6;
+ ymin := -3; ymax := 6;
+ drawoptions(withpen pencircle scaled 1bp withcolor 0.8white);
+ drawarrow ((xmin,0)--(xmax,0)) transformed T;
+ drawarrow ((0,ymin)--(0,ymax)) transformed T;
+ newBPolynomial.f(-0.25, 0.5, 2, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
+ f := f.getPath(-2.5, 4.2);
+ g := g.getPath(-1, 5);
+ A := buildcycle(g, reverse f);
+ %%% Fill area with pattern.
+ drawoptions();
+ hatchoptions(withcolor (0.6, 0.3, 0.3));
+ hatchfill A transformed T
+ withcolor (-45, 2mm, -0.5bp) withcolor (45, 2mm, -0.5bp);
+ drawoptions(withpen pencircle scaled 1bp);
+ draw f transformed T;
+ draw g transformed T dashed evenly scaled 2;
+\end{listing}
+
+
+\appendix
+\section{Calculating \B\ curves}\label{app:mathematics}
+\subsection{Polynomials}\label{app:polynomials}
+%Internally, paths are \B\ curves and MetaPost is able to calculate the points along such a curve.%
+%\footnote{Since PostScript has a concept of \B\ curves, too, for MetaPost drawing a path is simply an act of copying the parameters of the corresponding \B\ curve into PostScript output. But nonetheless MetaPost \emph{can} calculate points on a \B\ curve.}
+%
A \B\ curve $P(t)$ with end points $A=(x_A,y_A)$ and $D=(x_D,y_D)$ and control points $B=(x_B,y_B)$ and $C=(x_C,y_C)$ is defined as~\cite{mfbook}
\begin{equation}
P(t) = \left(
@@ -420,6 +621,16 @@ Additionally, we know that $D=(x_D,y_D)$ is a point on the polynomial. Therefor
Equations~\ref{eq:yA} to~\ref{eq:yC} of the original equation system and the new equations~\ref{eq:xA'} to~\ref{eq:yD'} constitute the modified equation system, that is solved in \pkg.
+\subsection{Square and cubic roots}\label{app:roots}
+When requesting the \B\ curve of a root function, the \pkg\ package first calculates the inverse function, then calculates the corresponding path and finally reflects that on the function $f(x)=x$ to get the inverse again.
+
+The inverse functions of the root functions from equations~\ref{eq:square} and~\ref{eq:cubic} are
+\begin{align}
+ \widetilde f_{sqr}(y) & = \left(\frac{y-w}{u}\right)^2 - v = 0 y^3 + \frac{1}{u^2} y^2 + \frac{-2w}{u^2} y + \frac{w^2}{u^2} - v \\
+ \widetilde f_{cub}(y) & = \left(\frac{y-w}{u}\right)^3 - v = \frac{1}{u^3} y^3 + \frac{-3w}{u^3} y^2 + \frac{3w^2}{u^3} y + \frac{w^3}{u^3} - v
+\end{align}
+which both are clearly polynomials.
+
\nobreak
\bigskip
\raggedright
@@ -430,8 +641,10 @@ Equations~\ref{eq:yA} to~\ref{eq:yC} of the original equation system and the new
\begin{thebibliography}{999}
+\bibitem{mp:metafun} \textsc{Hagen}, Hans, \emph{metafun}, \url{http://www.pragma-ade.com/general/manuals/metafun-p.pdf}
\bibitem{latex:numprint} \textsc{Harders}, Harald, \emph{The numprint package}, 2007, \url{CTAN:macros/latex/contrib/numprint/numprint.pdf}
\bibitem{mp:graph} \textsc{Hobby}, John~D., \emph{Drawing graphs with MetaPost}, \url{http://www.tug.org/docs/metapost/mpgraph.pdf}
+\bibitem{mp:hatching} \textsc{Jackowski}, B., \emph{hatching.mp}, \url{CTAN:graphics/metapost/contrib/macros/hatching/README}
\bibitem{mfbook} \textsc{Knuth}, Donald~E., \emph{The METAFONTbook}, Addison-Wesley, Reading, Massachusetts, 1986, (Computers \& Typesetting, C)
\bibitem{mp:splines} \textsc{Luecking}, Dan, \emph{Macros to compute splines}, 2005, \url{CTAN:graphics/metapost/contrib/macros/splines/splines.pdf}
\bibitem{mp:latexmp} \textsc{Morawski}, Jens-Uwe, \emph{latexMP}, 2005, \url{CTAN:graphics/metapost/contrib/macros/latexmp/doc/latexmp.pdf}
diff --git a/Master/texmf-dist/doc/metapost/bpolynomial/examples.mp b/Master/texmf-dist/doc/metapost/bpolynomial/examples.mp
index 1d32a2f8f0b..8caa5ced684 100644
--- a/Master/texmf-dist/doc/metapost/bpolynomial/examples.mp
+++ b/Master/texmf-dist/doc/metapost/bpolynomial/examples.mp
@@ -1,9 +1,11 @@
input bpolynomial;
+input metafun
input graph
+input hatching
prologues := 3;
transform T;
-T = identity xscaled 10mm yscaled 1mm;
+T := identity xscaled 10mm yscaled 1mm;
beginfig(1);
newBPolynomial.f(2, 0, -3, -1);
@@ -14,81 +16,75 @@ endfig;
beginfig(2);
newBPolynomial.f(2, 0, -3, -1);
draw f.getPath(-2, 2) transformed T;
- x := 1.5;
- show (x, f.eval(x));
- dotlabeldiam := 2bp;
- dotlabel.ulft(btex $(1.5, 1.25)$ etex, (x, f.eval(x)) transformed T);
+ draw f.getTangent(-0.5)(-1, 1) transformed T;
endfig;
beginfig(3);
+ dotlabeldiam := 2bp;
+ labeloffset := 10bp;
newBPolynomial.f(2, 0, -3, -1);
draw f.getPath(-2, 2) transformed T;
- draw f.getTangent(-1, -1, 1) transformed T;
+ x := -0.5;
+ show (x, f.eval(x));
+ draw f.getTangent(x)(-1, 1) transformed T;
+ dotlabel.top(btex $(-0.5, 0.25)$ etex, (x, f.eval(x)) transformed T);
endfig;
+labeloffset := 3bp;
beginfig(4);
newBPolynomial.f(2, 0, -3, -1);
draw f'.getPath(-2, 2) transformed T;
- draw f'.getTangent(1, -1, 1) transformed T;
+ draw f'.getTangent(-0.25)(-1, 1) transformed T;
endfig;
beginfig(5);
-numeric u;
-u := 0.5cm;
- %%% Draw a coordinate system.
- xmin := -5; xmax := 6;
- ymin := -5; ymax := 6;
- drawarrow ((xmin,0)--(xmax,0)) scaled u;
- drawarrow ((0,ymin)--(0,ymax)) scaled u;
- drawoptions(withpen pencircle scaled 1bp);
- %%% Define polynomial f of degree 2.
-path f[];
- newBPolynomial.f(0, 0.5, -2, 0);
- f1 := f.getPath(-2, 0);
- f2 := f.getPath(0, 4);
- f3 := f.getPath(4, 5.5);
- draw f1 scaled u dashed evenly scaled 2;
- draw f3 scaled u dashed evenly scaled 2;
- draw f2 scaled u dashed withdots
- withpen pencircle scaled 1.5bp withcolor .5white;
- %%% Define polynomial g of degree 3.
-path g;
- newBPolynomial.g(0.3, 0, -3, -1);
- g := g.getPath(-3.5, 4);
- show g;
- draw g scaled u;
- %%% Write table with some points of g to log file.
- show "Polynomial: " & decimal g.a & "x^3+" & decimal g.b
- & "x^2+" & decimal g.c & "x+" & decimal g.d;
- for x=-5 upto 5:
- show (x, g.eval(x));
- endfor
+ T := identity scaled 10mm;
+ newBSqrRoot.s(1,0,0);
+ newBCubRoot.c(1,0,0);
+ draw s.getPath(0,6) transformed T;
+ draw c.getPath(0,6) transformed T;
+ draw s.getTangent(3)(-2, 2) transformed T;
endfig;
+T := identity xscaled 10mm yscaled 1mm;
beginfig(6);
-path f,g;
+ draw getBezierFromPolynomial(2, 0, -3, -1)(-2, 2) transformed T;
+endfig;
+
+
+beginfig(11);
+path f, g;
xmin := -7; xmax := 7;
ymin := -7; ymax := 7;
- newBPolynomial.f(0, 0.5, -2, 0);
+ %%% Define polynomials f and g.
+ newBPolynomial.f(0.3, 0, -3, -1);
f := f.getPath(xmin, xmax);
- newBPolynomial.g(0.3, 0, -3, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
g := g.getPath(xmin, xmax);
+ %%% Draw graph.
draw begingraph(10cm, 6cm);
setrange(xmin,ymin, xmax,ymax);
autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
drawoptions(withpen pencircle scaled 1bp);
- gdraw f dashed evenly scaled 2;
- gdraw g;
+ gdraw f;
+ gdraw g dashed evenly scaled 2;
drawoptions();
endgraph;
+ show f;
+ %%% Write table with some points of f to log file.
+ show "Polynomial: " & decimal f.a & "x^3 + " &
+ decimal f.b & "x^2 + " & decimal f.c & "x + " & decimal f.d;
+ for x=-5 upto 5:
+ show (x, f.eval(x));
+ endfor
endfig;
-beginfig(7);
+beginfig(12);
xmin := -6; xmax := 6;
ymin := -6; ymax := 6;
newBPolynomial.f(0.3, -0.5, -0.5, -1);
@@ -104,12 +100,12 @@ beginfig(7);
gdraw f'''.getPath(-5, 5) withcolor .6white;
%%% Draw tangents and mark points.
x := 2;
- drawoptions(withcolor red+.6(green+blue));
- gdraw f.getTangent(x, -2, 2);
- gdraw f'.getTangent(x, -1, 1);
- gdraw f''.getTangent(x, -2, 2);
- gdraw f'''.getTangent(x, -2, 2);
- drawoptions(withcolor blue+.6(red+green));
+ drawoptions(withcolor (1, 0.6, 0.6));
+ gdraw f.getTangent(x)(-2, 2);
+ gdraw f'.getTangent(x)(-1, 1);
+ gdraw f''.getTangent(x)(-2, 2);
+ gdraw f'''.getTangent(x)(-2, 2);
+ drawoptions(withcolor (0.6, 0.6, 1));
dotlabeldiam := 2.5bp;
gdotlabel("", (x, f.eval(x)));
gdotlabel("", (x, f'.eval(x)));
@@ -119,4 +115,157 @@ beginfig(7);
endgraph;
endfig;
+
+beginfig(13);
+path f, g, A;
+ xmin := -3; xmax := 6;
+ ymin := -3; ymax := 6;
+ newBPolynomial.f(-0.25, 0.5, 2, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
+ f := f.getPath(-2.5, 5.5);
+ g := g.getPath(-1.5, 5.5);
+ %%% Find area between f and g.
+ A := buildcycle(g, reverse f);
+ draw begingraph(10cm, 6cm);
+ setrange(xmin,ymin, xmax,ymax);
+ autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
+ %%% Fill area with transparent colour.
+ gfill A withcolor transparent (1, .3, (1, 0.5, 0));
+ drawoptions(withpen pencircle scaled 1bp);
+ gdraw f;
+ gdraw g dashed evenly scaled 2;
+ drawoptions();
+ endgraph;
+endfig;
+
+
+beginfig(14);
+path f, g, A;
+ T := identity xscaled 10mm yscaled 6mm;
+ %%% Draw coordinate system.
+ xmin := -3; xmax := 6;
+ ymin := -3; ymax := 6;
+ drawoptions(withpen pencircle scaled 1bp withcolor 0.8white);
+ drawarrow ((xmin,0)--(xmax,0)) transformed T;
+ drawarrow ((0,ymin)--(0,ymax)) transformed T;
+ newBPolynomial.f(-0.25, 0.5, 2, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
+ f := f.getPath(-2.5, 4.2);
+ g := g.getPath(-1, 5);
+ A := buildcycle(g, reverse f);
+ %%% Fill area with pattern.
+ drawoptions();
+ hatchoptions(withcolor (0.6, 0.3, 0.3));
+ hatchfill A transformed T
+ withcolor (-45, 2mm, -0.5bp) withcolor (45, 2mm, -0.5bp);
+ drawoptions(withpen pencircle scaled 1bp);
+ draw f transformed T;
+ draw g transformed T dashed evenly scaled 2;
+endfig;
+
+
+%%% The following figures work around a bug in metafun's
+%%% mp-form.mp package for the original figures 11 to 13.
+%%% The bug shows up when rendering negative numbers
+%%% on corrdinate axes using macro 'format'.
+beginfig(21);
+path f, g;
+ xmin := -7; xmax := 7;
+ ymin := -7; ymax := 7;
+ %%% Define polynomials f and g.
+ newBPolynomial.f(0.3, 0, -3, -1);
+ f := f.getPath(xmin, xmax);
+ newBPolynomial.g(0, 0.5, -2, 0);
+ g := g.getPath(xmin, xmax);
+ %%% Draw graph.
+ draw begingraph(10cm, 6cm);
+ setrange(xmin,ymin, xmax,ymax);
+% autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
+ for i=xmin+1 step 2 until xmax-1:
+ grid.bot(decimal i, i) dashed evenly withcolor .9white;
+ endfor
+ for i=ymin+1 step 2 until ymax-1:
+ grid.lft(decimal i, i) dashed evenly withcolor .9white;
+ endfor
+ drawoptions(withpen pencircle scaled 1bp);
+ gdraw f;
+ gdraw g dashed evenly scaled 2;
+ drawoptions();
+ endgraph;
+ show f;
+ %%% Write table with some points of f to log file.
+ show "Polynomial: " & decimal f.a & "x^3 + " &
+ decimal f.b & "x^2 + " & decimal f.c & "x + " & decimal f.d;
+ for x=-5 upto 5:
+ show (x, f.eval(x));
+ endfor
+endfig;
+
+
+beginfig(22);
+ xmin := -6; xmax := 6;
+ ymin := -6; ymax := 6;
+ newBPolynomial.f(0.3, -0.5, -0.5, -1);
+ draw begingraph(10cm, 6cm);
+ setrange(xmin,ymin, xmax,ymax);
+% autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
+ for i=xmin step 2 until xmax:
+ grid.bot(decimal i, i) dashed evenly withcolor .9white;
+ endfor
+ for i=ymin step 2 until ymax:
+ grid.lft(decimal i, i) dashed evenly withcolor .9white;
+ endfor
+ drawoptions(withpen pencircle scaled 1bp);
+ %%% Draw f and its derivatives f', f'', f'''.
+ gdraw f.getPath(xmin, xmax);
+ gdraw f'.getPath(xmin, xmax) dashed evenly scaled 2;
+ gdraw f''.getPath(xmin, xmax) dashed withdots
+ withpen pencircle scaled 2bp;
+ gdraw f'''.getPath(-5, 5) withcolor .6white;
+ %%% Draw tangents and mark points.
+ x := 2;
+ drawoptions(withcolor (1, 0.6, 0.6));
+ gdraw f.getTangent(x)(-2, 2);
+ gdraw f'.getTangent(x)(-1, 1);
+ gdraw f''.getTangent(x)(-2, 2);
+ gdraw f'''.getTangent(x)(-2, 2);
+ drawoptions(withcolor (0.6, 0.6, 1));
+ dotlabeldiam := 2.5bp;
+ gdotlabel("", (x, f.eval(x)));
+ gdotlabel("", (x, f'.eval(x)));
+ gdotlabel("", (x, f''.eval(x)));
+ gdotlabel("", (x, f'''.eval(x)));
+ drawoptions();
+ endgraph;
+endfig;
+
+
+beginfig(23);
+path f, g, A;
+ xmin := -3; xmax := 6;
+ ymin := -3; ymax := 6;
+ newBPolynomial.f(-0.25, 0.5, 2, -1);
+ newBPolynomial.g(0, 0.5, -2, 0);
+ f := f.getPath(-2.5, 5.5);
+ g := g.getPath(-1.5, 5.5);
+ %%% Find area between f and g.
+ A := buildcycle(g, reverse f);
+ draw begingraph(10cm, 6cm);
+ setrange(xmin,ymin, xmax,ymax);
+% autogrid(grid.bot, grid.lft) dashed evenly withcolor .9white;
+ for i=xmin+1 step 2 until xmax:
+ grid.bot(decimal i, i) dashed evenly withcolor .9white;
+ endfor
+ for i=ymin+1 step 2 until ymax:
+ grid.lft(decimal i, i) dashed evenly withcolor .9white;
+ endfor
+ %%% Fill area with transparent colour.
+ gfill A withcolor transparent (1, .3, (1, 0.5, 0));
+ drawoptions(withpen pencircle scaled 1bp);
+ gdraw f;
+ gdraw g dashed evenly scaled 2;
+ drawoptions();
+ endgraph;
+endfig;
+
end
diff --git a/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp b/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp
index f1c0129bb94..e4f27a434a1 100644
--- a/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp
+++ b/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp
@@ -7,73 +7,152 @@
% license is in http://www.latex-project.org/lppl.txt
%
+%%% Identify yourself.
if known bpolynomial_fileversion: endinput fi;
string bpolynomial_fileversion;
-bpolynomial_fileversion := "v0.4 (2007/11/28)";
+bpolynomial_fileversion := "v0.5 (2007/12/12)";
message "Loading bpolynomial " & bpolynomial_fileversion;
+%%% Main user macro for defining polynomials.
+%%% Arguments are a suffix and the coefficients
+%%% of the function a*x^3 + b*x^2 + c*x + d.
vardef newBPolynomial@#(expr a, b, c, d)=
- defineBPolynomial.@#(a, b, c, d);
- defineBPolynomial.@#'(0, 3a, 2b, c);
- defineBPolynomial.@#''(0, 0, 6a, 2b);
- defineBPolynomial.@#'''(0, 0, 0, 6a);
+ bpolynomial__defineBPolynomial.@#(a, b, c, d);
+ bpolynomial__defineBPolynomial.@#'(0, 3a, 2b, c);
+ bpolynomial__defineBPolynomial.@#''(0, 0, 6a, 2b);
+ bpolynomial__defineBPolynomial.@#'''(0, 0, 0, 6a);
enddef;
-%%% This macro defines two macros @#.eval and @#.getPath.
-%%% Parameters are the coefficients of the polynomial a*x^3 + b*x^2 + c*x + d.
-vardef defineBPolynomial@#(expr ca,cb,cc,cd)=
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d between two points A and D.
+%%% This macro is the heart of this package and is used by
+%%% several other macros.
+%%% Arguments are the coefficients of the polynomial and the
+%%% start and end point of the graph/path.
+vardef bpolynomial__getBezierFromPolynomial(expr a, b, c, d, A, D)=
+save xA,xB,xC,xD,yA,yB,yC,yD;
+save xl,yl,xr,yr,dx;
+numeric xA,xB,xC,xD,yA,yB,yC,yD;
+numeric xl,yl,xr,yr,dx;
+ xl := xpart A;
+ yl := ypart A;
+ xr := xpart D;
+ yr := ypart D;
+ dx := xpart D - xpart A;
+ %%% Original equation system for x values.
+% xA = xl;
+% 3(xB - xA) = dx;
+% 3(xC - 2xB + xA) = 0;
+% xD - 3xC + 3xB - xA = 0;
+ %%% Modified equation system.
+ xA := xl;
+ xB := xl + dx/3;
+ xC := xr - dx/3;
+ xD := xr;
+ %%% Original equation system for y values.
+% yA = ((a*xl + b)*xl + c)*xl + d;
+% 3(yB - yA) = dx*((3a*xl + 2b)*xl + c);
+% 3(yC - 2yB + yA) = dx*dx*(3a*xl + b);
+% yD - 3yC + 3yB - yA = a*dx*dx*dx;
+ %%% Modified equation system.
+ yA := yl;
+ 3(yB - yA) = dx*((3a*xl + 2b)*xl + c);
+ 3(yC - 2yB + yA) = dx*dx*(3a*xl + b);
+ yD := yr;
+ %%% Return path A..controls B and C..D.
+ (xA,yA)..controls (xB,yB) and (xC,yC)..(xD,yD)
+enddef;
+
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d in the range [xl, xr].
+%%% Arguments are the coefficients of the polynomial and the
+%%% range boundaries of the graph/path.
+vardef getBezierFromPolynomial(expr a, b, c, d, xl, xr)=
+ bpolynomial__getBezierFromPolynomial(a, b, c, d,
+ (xl, ((a*xl+b)*xl+c)*xl+d),
+ (xr, ((a*xr+b)*xr+c)*xr+d))
+enddef;
+
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d in the range [xl, xr].
+%%% Arguments are the coefficients of the polynomial and the
+%%% range boundaries of the graph/path.
+vardef getBezierFromSqrRoot(expr u, v, w, xl, xr)=
+save yl, yr;
+numeric yl,yr;
+ if (xl >= -v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -v & "!";
+ yl := -v;
+ fi
+ if (xr >= -v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -v & "!";
+ yr := -v;
+ fi
+ bpolynomial__getBezierFromPolynomial(0, 1/u/u, -2*w/u/u, (w/u)*(w/u)-v,
+ (u*sqrt(yl+v)+w, yl),
+ (u*sqrt(yr+v)+w, yr)) reflectedabout ((0,0),(1,1))
+enddef;
+
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d in the range [xl, xr].
+%%% Arguments are the coefficients of the polynomial and the
+%%% range boundaries of the graph/path.
+vardef getBezierFromCubRoot(expr u, v, w, xl, xl)=
+save yl, yr;
+numeric yl,yr;
+ if (xl >= -v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -v & "!";
+ yl := -v;
+ fi
+ if (xr >= -v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -v & "!";
+ yr := -v & "!";
+ fi
+ bpolynomial__getBezierFromPolynomial(1/u/u/u, -3w/u/u/u, 3(w/u)*(w/u)/u, (w/u)*(w/u)*(w/u)-v,
+ (u*((yl+v)**(1/3))+w, yl),
+ (u*((yr+v)**(1/3))+w, yr)) reflectedabout ((0,0),(1,1))
+enddef;
+
+
+%%% This internal macro defines a new polynomial.
+%%% Arguments are a suffix macro and the coefficients
+%%% of the polynomial a*x^3 + b*x^2 + c*x + d.
+vardef bpolynomial__defineBPolynomial@#(expr ca,cb,cc,cd)=
numeric @#.a, @#.b, @#.c, @#.d;
%%% Save coefficients for later access.
- %%% For instance, variable @#.a refers to coefficient a of polynomial @#.
+ %%% Variable @#.a refers to coefficient a of polynomial @#.
@#.a := ca;
@#.b := cb;
@#.c := cc;
@#.d := cd;
-
- %%% Define macro that returns values of polynomial @#.
- %%% Parameter is an x value.
+ %%% This macro returns values of polynomial @#.
+ %%% Argument is an x value.
vardef @#.eval(expr x)=
(((@#.a*x + @#.b)*x + @#.c)*x + @#.d)
enddef;
-
- %%% Define a macro that returns a path of the polynomial
- %%% on a given intervall [xl, xr].
+ %%% This macro returns the path corresponding to polynomial @#
+ %%% on the intervall [xl, xr].
vardef @#.getPath(expr xl,xr)=
- save xA,xB,xC,xD,yA,yB,yC,yD;
- save dx;
- numeric xA,xB,xC,xD,yA,yB,yC,yD;
- numeric dx;
- dx := xr - xl;
- %%% Original equation system for x values.
-% xA = xl;
-% 3(xB - xA) = dx;
-% 3(xC - 2xB + xA) = 0;
-% xD - 3xC + 3xB - xA = 0;
- %%% Modified equation system.
- xA := xl;
- xB := xl + dx/3;
- xC := xr - dx/3;
- xD := xr;
- %%% Original equation system for y values.
-% yA = ((@#.a*xl + @#.b)*xl + @#.c)*xl + @#.d;
-% 3(yB - yA) = dx*((3@#.a*xl + 2@#.b)*xl + @#.c);
-% 3(yC - 2yB + yA) = dx*dx*(3@#.a*xl + @#.b);
-% yD - 3yC + 3yB - yA = @#.a*dx*dx*dx;
- %%% Modified equation system.
- yA := @#.eval(xl);
- 3(yB - yA) = dx*((3@#.a*xl + 2@#.b)*xl + @#.c);
- 3(yC - 2yB + yA) = dx*dx*(3@#.a*xl + @#.b);
- yD := @#.eval(xr);
- %%% Return path A..controls B and C..D.
- (xA,yA)..controls (xB,yB) and (xC,yC)..(xD,yD)
+ bpolynomial__getBezierFromPolynomial(@#.a, @#.b, @#.c, @#.d, (xl, @#.eval(xl)), (xr, @#.eval(xr)))
enddef;
-
- %%% Define macro that returns a path tangent to @# at point (x, f(x))
- %%% covering interval (x+xm, x+xp).
+ %%% This macro returns a path tangent to @# at point (x, f(x))
+ %%% covering the interval [x+xm, x+xp].
vardef @#.getTangent(expr x, xm, xp)=
save m, y;
numeric m, y;
@@ -83,3 +162,141 @@ numeric @#.a, @#.b, @#.c, @#.d;
enddef;
enddef;
+
+
+%%% This macro defines a new square root.
+%%% Arguments are a suffix macro and the parameters
+%%% of the function u*(x + v)^(1/2) + w.
+vardef newBSqrRoot@#(expr cu,cv,cw)=
+numeric @#.a, @#.b, @#.c, @#.d;
+numeric @#.u, @#.v, @#.w;
+ %%% Save parameters for later access.
+ %%% Variable @#.v refers to parameters of square root @#.
+ %%% Variables @#.a to @#.d store the coefficients of the
+ %%% corresponding polynomial.
+ @#.u := cu;
+ @#.v := cv;
+ @#.w := cw;
+ @#.a := 0;
+ @#.b := 1/cu/cu;
+ @#.c := -2*cw/cu/cu;
+ @#.d := (cw/cu)*(cw/cu)-cv;
+
+ %%% This macro returns values of polynomial @#.
+ %%% Argument is an x value.
+ vardef @#.eval(expr x)=
+ if (x >= -@#.v):
+ @#.u*sqrt(x + @#.v) + @#.w
+ else:
+ message "Package bpolynomial warning: Cannot evaluate function at x = " & decimal x & "!";
+ @#.w
+ fi
+ enddef;
+
+ %%% This macro returns the path corresponding to square root @#
+ %%% on the intervall [yl, yr]. The path of the corresponing
+ %%% polynomial is computed and then transformed.
+ vardef @#.getPath(expr xl,xr)=
+ save yl, yr;
+ numeric yl, yr;
+ if (xl >= -@#.v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -@#.v & "!";
+ yl := -@#.v;
+ fi
+ if (xr >= -@#.v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -@#.v & "!";
+ yr := -@#.v;
+ fi
+ bpolynomial__getBezierFromPolynomial(@#.a, @#.b, @#.c, @#.d, (@#.eval(yl), yl), (@#.eval(yr), yr))
+ reflectedabout ((0,0),(1,1))
+ enddef;
+
+ %%% This macro returns a path tangent to square root @#
+ %%% at point (x, f(x)) covering the interval [x+xm, x+xp].
+ vardef @#.getTangent(expr x, epsl, epsr)=
+ save m, y;
+ numeric m, y;
+ if (x >= -@#.v):
+ m := @#.u/(2sqrt(x + @#.v));
+ y := @#.eval(x);
+ (x+epsl, y + m*epsl) -- (x+epsr, y + m*epsr)
+ else:
+ message "Package bpolynomial warning: Cannot draw tangent at x = " & decimal x & "!";
+ (-@#.v, @#.w)--(-@#.v, @#.w+1)
+ fi
+ enddef;
+
+enddef;
+
+
+%%% This macro defines a new cubic root.
+%%% Arguments are a suffix macro and the parameters
+%%% of the function u*(x + v)^(1/3) + w.
+vardef newBCubRoot@#(expr cu,cv,cw)=
+numeric @#.a, @#.b, @#.c, @#.d;
+numeric @#.u, @#.v, @#.w;
+ %%% Save parameters for later access.
+ %%% Variable @#.v refers to parameters of cubic root @#.
+ %%% Variables @#.a to @#.d store the coefficients of the
+ %%% corresponding polynomial.
+ @#.u := cu;
+ @#.v := cv;
+ @#.w := cw;
+ @#.a := 1/cu/cu/cu;
+ @#.b := -3cw/cu/cu/cu;
+ @#.c := 3(cw/cu)*(cw/cu)/cu;
+ @#.d := (cw/cu)*(cw/cu)*(cw/cu)-cv;
+
+ %%% This macro returns values of polynomial @#.
+ %%% Argument is an x value.
+ vardef @#.eval(expr x)=
+ if (x >= -@#.v):
+ @#.u*((x+@#.v)**(1/3)) + @#.w
+ else:
+ message "Package bpolynomial warning: Cannot evaluate function at x = " & decimal x & "!";
+ @#.w
+ fi
+ enddef;
+
+ %%% This macro returns the path corresponding to cubic root @#
+ %%% on the intervall [yl, yr]. The path of the corresponing
+ %%% polynomial is computed and then transformed.
+ vardef @#.getPath(expr xl,xr)=
+ save yl, yr;
+ numeric yl, yr;
+ if (xl >= -@#.v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -@#.v & "!";
+ yl := -@#.v;
+ fi
+ if (xr >= -@#.v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -@#.v & "!";
+ yr := -@#.v;
+ fi
+ bpolynomial__getBezierFromPolynomial(@#.a, @#.b, @#.c, @#.d, (@#.eval(yl), yl), (@#.eval(yr), yr))
+ reflectedabout ((0,0),(1,1))
+ enddef;
+
+ %%% This macro returns a path tangent to cubic root @#
+ %%% at point (x, f(x)) covering the interval [x+xm, x+xp].
+ vardef @#.getTangent(expr x, epsl, epsr)=
+ save m, y;
+ numeric m, y;
+ if (x >= -@#.v):
+ m := @#.u/3/((x + @#.v)**(2/3));
+ y := @#.eval(x);
+ (x+epsl, y + m*epsl) -- (x+epsr, y + m*epsr)
+ else:
+ message "Package bpolynomial warning: Cannot draw tangent at x = " & decimal x & "!";
+ (-@#.v, @#.w)--(-@#.v, @#.w+1)
+ fi
+ enddef;
+
+enddef;