diff options
author | Karl Berry <karl@freefriends.org> | 2011-08-01 00:48:08 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-08-01 00:48:08 +0000 |
commit | 2dd820f377c1dccbc53a6d34d604b7b4a5ed317c (patch) | |
tree | 9c266429eea522ff80928adc70be7abec8277c0c /Master | |
parent | 07db9a5835ec1aaa508040c50590c2d0f8c70d84 (diff) |
pst-bspline (31jul11)
git-svn-id: svn://tug.org/texlive/trunk@23294 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/generic/pst-bspline/README | 4 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.pdf | bin | 111493 -> 142662 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.tex | 165 | ||||
-rw-r--r-- | Master/texmf-dist/dvips/pst-bspline/pst-bspline.pro | 68 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/pst-bspline/pst-bspline.tex | 163 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/pst-bspline/pst-bspline.sty | 2 |
6 files changed, 349 insertions, 53 deletions
diff --git a/Master/texmf-dist/doc/generic/pst-bspline/README b/Master/texmf-dist/doc/generic/pst-bspline/README index 5224a25cf46..62d5a1ef35c 100644 --- a/Master/texmf-dist/doc/generic/pst-bspline/README +++ b/Master/texmf-dist/doc/generic/pst-bspline/README @@ -2,10 +2,10 @@ %% %% Michael Sharpe <msharpe@ucsd.edu> %% -%% Version 1.41, 2010/10/19 +%% Version 1.44, 2011/07/30 %% %% License: Free -This package draws uniform, cubic B-spline curves, open and closed, based on a sequence of B-spline control points. There is also code which permits drawing the open or closed cubic B-spline curve interpolating a sequence of points. This version adds a \thickBspline macro. +This package draws uniform, cubic B-spline curves, open and closed, based on a sequence of B-spline control points. There is also code which permits drawing the open or closed cubic B-spline curve interpolating a sequence of points. This update adds a number of macros allowing B-spline curves to be used as if they were parametric curves. The .tex and .sty files should be installed in a folder searched by TeX. All documentation is in pst-bspline-doc.pdf.
\ No newline at end of file diff --git a/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.pdf b/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.pdf Binary files differindex 7b4beb03b8d..f8392d5358c 100644 --- a/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.pdf +++ b/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.pdf diff --git a/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.tex b/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.tex index 8e034e19af3..d88db518937 100644 --- a/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.tex +++ b/Master/texmf-dist/doc/generic/pst-bspline/pst-bspline-doc.tex @@ -7,6 +7,17 @@ \usepackage{multido,pst-node,pst-bspline,pstricks-add} \usepackage{amssymb} \usepackage[parfill]{parskip} +\usepackage{lmodern} +\usepackage[scaled=.82]{luximono}%requires T1+textcomp +\usepackage[T1]{fontenc} +\newcommand\textSMC[1]{{\SMC #1}} +\newcommand\acro[1]{\textSMC{#1}\@} +\DeclareRobustCommand\cs[1]{\texttt{\char`\\#1}} +\usepackage[cal=boondoxo]{mathalfa} +\usepackage{textcomp} +%\usepackage{url} +%\def\url@ttstyle{% +% \@ifundefined{selectfont}{\def\UrlFont{\tt}}{\def\UrlFont{\ttfamily\small}}} \usepackage{hyperref} \hyphenation{Post-Script} %\date{} % Activate to display a given date or no date @@ -15,17 +26,40 @@ \large Michael Sharpe\\[10pt] msharpe@ucsd.edu} \end{center} -A cubic uniform B-spline curve with control points $B_0 \ldots B_n$ is a curve parametrized by the interval $[0,n]$, which is, except in degenerate cases, $C^2$-continuous (that is, has continuous curvature) and is on each interval $[k-1,k]$ given by a cubic B\'ezier curve whose control points are derived from the $(B_k)$. These curves are discussed in any reasonably modern text on Numerical Analysis. One easily accessible source is the UCLA lecture notes of Kirby Baker: +A cubic, uniform B-spline curve with control points $B_0 \ldots B_n$ ($n \ge 2$) is a curve parametrized by the interval $[0,n]$, which is, except in degenerate cases, $C^2$-continuous (that is, has continuous curvature) and is on each interval $[k-1,k]$ ($0<k\le n$ an integer) given by a cubic B\'ezier curve whose control points are derived from the $(B_k)$. These curves are discussed in any reasonably modern text on Numerical Analysis. One easily accessible source is the UCLA lecture notes of Kirby Baker: \noindent\url{http://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf} -I'll focus on two special cases: (i) relaxed, uniform B-splines; (ii) periodic, uniform B-splines. Uniform refers to the condition mentioned in the first paragraph: each B\'ezier sub-curve is parametrized by an interval of length~1. Relaxed means that the curvature at the endpoints $t=0, t=n$ is zero. Periodic means in effect that the $B_i$ repeat periodically, and the curve generated is a closed curve. - -\section{Relaxed, Open B-spline} The algorithm has the following steps. +I'll focus on two special cases: (i) relaxed, uniform B-splines; (ii) periodic, uniform B-splines. `Uniform' refers to the condition mentioned in the first paragraph: each B\'ezier sub-curve is parametrized by an interval of length~1. `Relaxed' means that the curvature vanishes at the endpoints $t=0, t=n$. `Periodic' means in effect that the $B_i$ repeat periodically, and the curve generated is a closed curve. + +\section{Quick summary of the macros} +\begin{description} +\item[\cs{psbspline}(1,1)(3,0)(5,2)(4,5)] + draws the relaxed, uniform B-spline interpolating the specified points. +\item[\cs{psBspline}(1,1)(3,0)(5,2)(4,5)] draws the relaxed, uniform B-spline with specified control points. +\item[\cs{psBspline}\{B\}(1,1)(3,0)(5,2)(4,5)] draws the relaxed, uniform B-spline with specified control points, using \texttt{B} as basename for the constructed points. +\item[\cs{psBsplineE}(1,1)(3,0)(5,2)(4,5)] is the same as \cs{psBspline}(1,1)(3,0)(5,2)(4,5) except that it omits the first and last segments. +\item[\cs{psBsplineC}(1,1)(3,0)(5,2)(4,5)] extends the specified points periodically, drawing a closed curve with the specified points as control points. +\item[\cs{psBsplineNodes}\{B\}\{4\}] draws the relaxed, uniform B-spline with control points \texttt{B0}..{\tt B4}. +\item[\cs{psBsplineNodesE}\{B\}\{4\}] is the same as \cs{psBsplineNodes}\{B\}\{4\} except that it omits the first and last segments. +\item[\cs{psBsplineNodesC}\{B\}\{4\}] extends the node sequence periodically, drawing a closed curve with them as control points. +\item[\cs{beztobsp}(1,2)(-3,-4)(5,6)(-7,-8)\{B\}] creates nodes {\tt B0}..{\tt B3} for which the curve \cs{psBsplineNodesE}\{B\}\{3\} is identical to the B\'ezier curve determined by the specified points. (It does not draw the curve.) +\item[\cs{bspcurvepoints\{B\}\{5\}\{P\}}] creates PostScript arrays to describe a sequence of points along the curve that would be the result of the command \cs{psBsplineNodes}\{B\}\{5\}, naming those arrays {\tt P.X}, {\tt P.Y} (for position), {\tt PNormal.X}, {\tt PNormal.Y}, {\tt PDelta.X} and {\tt PDelta.Y}. (Nothing is drawn.) +\item[\cs{bspcurvepointsE\{B\}\{5\}\{P\}}] does the same as \cs{bspcurvepoints}, but omits the first and last segments. (Nothing is drawn.) +\item[\cs{bspNode\{P\}\{5\}\{1.3\}\{Q\}}] requires that you first run \cs{bspcurvepoints}{\tt[E]} to create PostScript arrays with basename {\tt P}. It then sets a node {\tt Q} at position $t=1.3$ on the curve. (Nothing is drawn.) +\item[\cs{bspFnNode\{P\}\{5\}\{2.3\}\{Q\}}] requires that you first run \cs{bspcurvepoints}{\tt[E]} to create PostScript arrays with basename {\tt P}. It then sets a node {\tt Q} at position $x=1.3$ on the curve. (Nothing is drawn.) The result is meaningful only for a B-spline curve that is the graph of a function of $x$ and where $x_0<x_1<\cdots$. +\item[\cs{psBsplineInterp\{S\}\{4\}}] will construct a sequence {\tt SB0}..{\tt SB4} for which the associated B-spline curve interpolates {\tt S0}..{\tt S4}. (Nothing is drawn---you have to then issue the command \cs{psBsplineNodes\{SB\}\{4\}}.) +\item[\cs{psBsplineInterpC\{S\}\{4\}}] will construct a sequence {\tt SB0}..{\tt SB5} for which the associated closed B-spline curve interpolates {\tt S0}..{\tt S4}. (Nothing is drawn---you have to then issue the command \cs{psBsplineNodesC\{SB\}\{5\}}.) +\item[\cs{thickBspline\{B\}\{5\}\{12pt\}\{<graphic to clip>\}}] defines a clipping path 12{\tt pt} wide around the B-spline curve with control points {\tt B0}..{\tt B5}, then draws the {\tt <graphic>} clipped to that path. +\item[\cs{bspcurvenodes\{P\}\{Q\}}] creates a node sequence {\tt Q0} {\tt Q1},... from the position data in the arrays {\tt P.X}, {\tt P.Y}. +\end{description} +Details and examples are provided below. + +\section{Relaxed, Open B-spline} The algorithm to generate such a curve from a sequence of control points $B_0$, $\cdots$, $B_n$ is as follows: \begin{itemize} -\item The curve starts at $B_0$ and ends at $B_n$. -\item Divide each line $B_{k-1}B_k$ into equal thirds, with subdivision points labeled $R_{k-1}$, $L_k$ respectively, so that $B_k$ has $L_k$ as its immediate neighbor to the left, and $R_k$ as its immediate neighbor to the right. +\item The curve starts at $B_0$ and ends at $B_n$. (Important: $n \ge 2$.) +\item Divide each line segment $B_{k-1}B_k$ into equal thirds, with subdivision points labeled $R_{k-1}$, $L_k$ respectively, so that $B_k$ has $L_k$ as its immediate neighbor to the left, and $R_k$ as its immediate neighbor to the right. \item For $0<k<n$, divide the line segment $L_kR_k$ in half, letting $S_k$ denote the midpoint. In effect, for $0< k<n$, $S_k=(B_{k-1}+4B_k+B_{k+1})/6$. \item Let $S_0=B_0$ and $S_n=B_n$. \item For $0<k\le n$, construct the cubic B\'ezier curve with control points $S_{k-1}$, $R_{k-1}$, $L_k$, $S_k$, parametrized by $k-1\le t\le k$. @@ -45,9 +79,9 @@ There is another optional argument that can be applied if you wish to be able to \noindent sets the root of the naming scheme to {\tt B}, the effect of which is that the B-spline control points will be nodes of type \verb|\pnode| with names {\tt B0}, {\tt B1} and so on, the other points being similarly named {\tt BL0}, {\tt BL1}, ... , {\tt BR0}, {\tt BR1}, ... , {\tt BS0}, {\tt BS1}, ... . For example, to draw a line between {\tt BL1} and {\tt BS4}, just use \verb|\ncline(BL1)(BS4)|. -The algorithm is implemented entirely in PSTricks code with PostScript specials, but no PostScript header file, depending for the most part on the flexibility of nodes, and above all the \verb|\multido| macro, which allows one to construct with relative ease items that look and feel like arrays. Use of \verb|\SpecialCoor| is essential. +The algorithm depends for the most part on the flexibility of nodes, and above all the \verb|\multido| macro, which allows one to construct with relative ease items that look and feel like arrays. Use of \verb|\SpecialCoor| is essential. -There is a closely related macro \verb|\psBsplineE| which removes the first and last B\'ezier segments, much as \verb|\psecurve| acts in relation to \verb|\pscurve|, allowing one one to draw B-splines with non-zero curvature at the endpoints. +There is a closely related macro \verb|\psBsplineE| which removes the first and last B\'ezier segments, much as \verb|\psecurve| acts in relation to \verb|\pscurve|, allowing one to draw B-splines with non-zero curvature at the endpoints. \begin{verbatim} \documentclass{article} @@ -60,17 +94,12 @@ There is a closely related macro \verb|\psBsplineE| which removes the first and \begin{pspicture}[showgrid=true](-.5,-.5)(6,5) \psBspline[showframe=true]{B}(.5,.5)(2,0)(5,2)(6,4)(4,5)(2,4) \multido{\i=0+1}{5}{\uput[20](B\i){B\i}} -\uput[90](B5){B5} -\uput[90](BS1){S1} -\uput[90](BS2){S2} -\uput[180](BS3){S3} -\uput[270](BS4){S4} -\uput[-45](BR1){R1} +\uput[90](B5){B5}\uput[90](BS1){S1}\uput[90](BS2){S2} +\uput[180](BS3){S3}\uput[270](BS4){S4}\uput[-45](BR1){R1} \uput[-45](BL2){L2} \end{pspicture} \end{document} \end{verbatim} - \vspace{1pc} \begin{center} \psset{unit=.6in} @@ -87,6 +116,7 @@ There is a closely related macro \verb|\psBsplineE| which removes the first and \end{pspicture} \end{center} +\newpage \begin{verbatim} \documentclass{article} \usepackage{pstricks} @@ -124,7 +154,19 @@ There is a closely related macro \verb|\psBsplineE| which removes the first and \uput[-45](BL2){L2} \end{pspicture} \end{center} - +\subsection{B\'ezier curves as B-spline curves} +Consider a B\'ezier curve $\mathcal{C}$ with control points $S_1$, $C_1$, $C_2$, $S_2$. To identify $\mathcal{C}$ as a B-spline curve of the type discussed above, consider the problem of finding the B-spline control points $B_0$, $B_1$, $B_2$, $B_3$ for which \verb|\psBsplineE| yields $\mathcal{C}$. This is a simple problem in linear algebra whose solution is: +\begin{verbatim} +B0=6S1-7C1+2C2 +B1=2C1-C2 +B2=-C1+2C2 +B3=6S2+2C1-7C2 +\end{verbatim} +In other words, any cubic B\'ezier curve may be considered to be the output of \verb|\psBsplineE| for the $B_i$ described above. In this way, all macros described for B-spline curves may be applied to an arbitrary B\'ezier curve as a special case. The macro +\begin{verbatim} +\beztobsp(S1)(C1)(C2)(S2){B} +\end{verbatim} +results in defining $B_0$,$\dots$,$B_3$ exactly as above. \section{Periodic B-spline} The result here is a closed curve. The algorithm is essentially the same as in the preceding case, except: \begin{itemize} @@ -187,6 +229,43 @@ defines a sequence of \verb|\pnode|s with the node root {\tt P}: {\tt P0}=(2,1.5 \psBsplineNodesE{<node root>}{<top index>} \end{verbatim} corresponding to the macros \verb|\psBspline|, \verb|\psBsplineC| and \verb|\psBsplineE|. The difference is that the macros with {\tt Nodes} in the name have as arguments the root node name and the last index, rather than the list of points. For example, with the above definition of {\tt P} in force, \verb|\psBsplineNodes{P}{2}| has exactly the same effect as \verb|\psBspline(2,1.5)(3,4)(5,1).| +\subsection{The \cs{bspcurvepoints} macros} +There are two macros that provide for B-spline curves essentially the same functionality as the \verb|\pscurvepoints| macro from {\tt pstricks-add}. (That macro takes as input a parametric curve and constructs as output (at the PostScript level) arrays of data associated with the curve: the positions of points along the curve, the increment from the previous point and a normal vector to the curve. The principal uses for such data are (i) the \verb|\pspolylineticks| macro from {\tt pstricks-add}, which allows placement of ticks and other marks along a curve that has been approximated by a polyline; (ii) the \cs{polyIntersections} macro from \textsf{pst-node}, which allows you to find the points of intersection of the curve (approximated by a polyline) and an arbitrary line.) The macros +\begin{verbatim} +\bspcurvepoints{<source name>}{<source max index>}{<dest. name>} +\bspcurvepointsE{<source name>}{<source max index>}{<dest. name>} +\end{verbatim} +work, in the first case, for a relaxed, uniform B-spline curve, and in the second, for such a curve with its initial and final segments removed, corresponding to the output from \verb|\psBsplineE| rather than \verb|\psBspline|. In both cases, you may set the keyword {\tt plotpoints} (default value: $50$) to change the number of sample points on each B\'ezier component. This will result in the construction of PostScript arrays with indices from $0$ to $n=$\textsf{num of segments}$\times$\textsf{(plotpoints-1)}. After running +\begin{verbatim} +\pnodes{B}(1,2)(3,-1)(4,1)(6,2)% define B0..B3 +\bspcurvepoints[plotpoint=11]{B}{3}{P} +\end{verbatim} +the following PostScript arrays are created, each indexed from 0 to 30: +\begin{verbatim} +P.X, P.Y (position) +PNormal.X, PNormal.Y (normal vector) +PDelta.X, PDelta.Y (increment from previous position) +\end{verbatim} +and these may be used in the usual way to create nodes. For example, +\begin{verbatim} +\pnode(! P.X 8 get P.Y 8 get){Q} +\pnode(! PNormal.X 8 get PNormal.Y get){Dir} +\psrline(Q)(1cm;{(Dir)}) +\end{verbatim} +places {\tt Q} at the position on the curve with index 8, defines {\tt Dir} to be a normal vector at that point, then draws a line from {\tt Q} of length {\tt 1cm} in the direction of that normal. +\subsection{Setting nodes on a B-spline curve} +To set a node at parameter value $t$ on a B-spline curve after running \cs{bspcurvepoints}{\tt[E]}, call the macro +\begin{verbatim} +\bspNode{<control point root>}{<top index>}{<t>}{<node name>} +\end{verbatim} +For example, if I have constructed a B-spline curve using control points $B_0$,$\dots$,$B_5$, then \verb|\bspNode{B}{5}{2.1}{Q}| defines a node named $Q$ at $t=2.1$. + +The macro \cs{bspcurvenodes\{P\}\{R\}} creates a node sequence {\tt R0}..{\tt Rn} at the locations specified by the arrays {\tt P.X}, {\tt P.Y}. (Those arrays must first have been created with one of the \cs{bspcurvepoints} macros.) +\subsection{B-spline function curves} +By this we mean an open B-spline curve which is the graph of a function $y=f(x)$ and whose orientation is toward the right. It is not analytically simple to specify a formula for $f$ in most cases, and to compute $y$ from $x$ involves (a) finding the index of the B\'ezier segment containing $x$; (b) solving the cubic $x(t)=x$ for $t$; (c) substituting in $y(t)$. The package provides a macro to perform these calculations after generating the data using \cs{bspcurvepoints}{\tt[E]}: +\begin{verbatim} +\bspfnNode{<control point root>}{<top index>}{<x0>}{<node name>} +\end{verbatim} \section{B-spline Interpolation} This is the inverse problem. Being given points $(S_k)_{0\le k\le n}$, the goal is to produce the B-spline control points $B_k$ leading to the points $S_k$, so that the associated B-spline curve interpolates the $S_k$. @@ -206,7 +285,7 @@ for the $B_k$. In matrix form, this becomes the tridiagonal system &1&4&1\\ &&\cdots&&1\\ &&&1&4\end{pmatrix} -\begin{pmatrix}B_1\\B_2\\B_3\\ \cdots\\ B_{n-1}\end{pmatrix}=ß +\begin{pmatrix}B_1\\B_2\\B_3\\ \cdots\\ B_{n-1}\end{pmatrix}= \begin{pmatrix}6S_1-S_0\\6S_2\\6S_3\\ \cdots\\6S_{n-1}-S_{n}\end{pmatrix} \] The LU decomposition of the tridiagonal matrix may be seen to take the form @@ -263,7 +342,7 @@ for the $B_k$, $1\le k\le n$. In matrix form, this becomes the system &1&4&1\\ &&\cdots&&1\\ 1&&&1&4\end{pmatrix} -\begin{pmatrix}B_1\\B_2\\B_3\\ \cdots\\ B_{n}\end{pmatrix}=ß +\begin{pmatrix}B_1\\B_2\\B_3\\ \cdots\\ B_{n}\end{pmatrix}= \begin{pmatrix}6S_1\\6S_2\\6S_3\\ \cdots\\6S_{n}\end{pmatrix} \] Let $(x_k,y_k)=6S_k$. We perform Gaussian elimination on the matrix @@ -366,19 +445,30 @@ Slight difference between psccurve and B-spline interpolation\\ \end{center} A B-spline curve can in many cases provide a good function interpolation mechanism, but the result is not guaranteed to be the graph of a function. \begin{verbatim} -\begin{center} -\begin{pspicture}[showgrid=true](-.5,-.5)(6,4) -\psdots(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5) +\begin{pspicture}(-.5,-.5)(6,4) +\psdots(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5)% +\pnodes{S}(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5)% S0..S5 +\psBsplineInterp{S}{5}% construct SB0..SB5 +\psBsplineNodes{SB}{5}% draw B-spline with control pts SB0..SB5 +\bspcurvepoints[plotpoints=10]{SB}{5}{P} +% construct the PS arrays +\bspFnNode{SB}{5}{4.5}{QQ}% node QQ on curve at x=4.5 +\psdot[linecolor=red](QQ)% \psaxes(0,0)(-.5,-.5)(6,4) -\psbspline(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5) \end{pspicture} -\end{center} \end{verbatim} +\vspace{1pc} \begin{center} \begin{pspicture}(-.5,-.5)(6,4) -\psdots(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5) -\psbspline(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5) +\psdots(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5)% +\pnodes{S}(0,3.5)(1,.5)(3,2.5)(4,0)(5,2)(6,.5)% S0..S5 +\psBsplineInterp{S}{5}%SB0..SB5 +\psBsplineNodes{SB}{5}% draw B-spline with control pts SB0..SB5 +\bspcurvepoints[plotpoints=10]{SB}{5}{P} +% construct the PS arrays +\bspFnNode{SB}{5}{4.5}{QQ}% node QQ on curve at x=4.5 +\psdot[linecolor=red](QQ)% \psaxes(0,0)(-.5,-.5)(6,4) \end{pspicture} \end{center} @@ -386,7 +476,6 @@ A B-spline curve can in many cases provide a good function interpolation mechani \begin{verbatim} \documentclass{article} -\usepackage{graphicx} \usepackage{pstricks} \usepackage{pst-bspline,pstricks-add} \begin{document} @@ -442,7 +531,8 @@ which creates a framework of B-spline control points {\tt SB0..SB3}. (The {\tt [linestyle=none]} may be omitted if you want the curve to show.) \item Create a clipping path of specified thickness around the interpolating curve and place graphics to be clipped: \begin{verbatim} -\thickBspline[plotpoints=50,linestyle=none]{S}{3}{20pt}{\psline[linecolor=red,linestyle=solid](0,0)(6,6)}% +\thickBspline[plotpoints=50,linestyle=none]{S}{3}{20pt}% +{\psline[linecolor=red,linestyle=solid](0,0)(6,6)}% \end{verbatim} (The {\tt [linestyle=none]} controls whether the clipping path is rendered, and {\tt plotpoints} controls the number of subdivisions of each B\'ezier component. Its default value is 50.) \end{itemize} @@ -476,18 +566,20 @@ The clipping path is drawn by default positively oriented so that objects are cl \end{center} \vspace{12pt} -The \verb|\thickBspline| macro works as expected in the closed (periodic) case, taking advantage of automatic incrementing of the nodecount. +The \verb|\thickBspline| macro works as expected in the closed (periodic) case, taking advantage of automatic incrementing of the nodecount. Note that \verb|\thickBspline| interprets thickness as visual, unaffected by possible differences between {\tt xunit} and {\tt yunit}. \begin{verbatim} \documentclass{article} \usepackage{pstricks} \usepackage{pst-bspline,pstricks-add} \begin{document} +\psset{yunit=1.5cm} \begin{pspicture}[showgrid=true](-.5,-.5)(6,5) -\pnodes{S}(1,0)(5,1)(4,4)(1,3)% -\psBsplineInterpC{S}{\Snodecount}% -% defines nodes SB0, SB1, SB2 etc --- the Bspline control points +\pnodes{S}(1.5,0)(5,1)(4,4)(1,3)% +\psBsplineInterpC{S}{3}% +% defines nodes SB0, SB1, SB2, SB3, SB4 --- the Bspline control points % increments \Snodecount by 1 for future macros +% Don't use C form of \psBsplineNodes with this new \Snodecount \psBsplineNodes[linestyle=none,showpoints=false]{SB}{\Snodecount}% % Constructs the Bezier control points SBR0, SBL1, SBR1, etc \thickBspline[linestyle=none]{S}{\Snodecount}{22pt}% @@ -499,14 +591,17 @@ The \verb|\thickBspline| macro works as expected in the closed (periodic) case, \vspace{12pt} \begin{center} +\psset{yunit=1.5cm} \begin{pspicture}[showgrid=true](-.5,-.5)(6,5) -\pnodes{S}(1,0)(5,1)(4,4)(1,3)% -\psBsplineInterpC{S}{\Snodecount}% -% defines nodes SB0, SB1, SB2 etc --- the Bspline control points +\pnodes{S}(1.5,0)(5,1)(4,4)(1,3)% +\psBsplineInterpC{S}{3}% +% defines nodes SB0, SB1, SB2, SB3 --- the Bspline control points % increments \Snodecount by 1 for future macros \psBsplineNodes[linestyle=none,showpoints=false]{SB}{\Snodecount}% % Constructs the Bezier control points SBR0, SBL1, SBR1, etc -\thickBspline[linestyle=none]{S}{\Snodecount}{22pt}{\psframe[fillstyle=vlines](-1,-1)(6,6)}% +\thickBspline[linestyle=none]{S}{\Snodecount}{22pt}% +{\psframe[fillstyle=vlines](-1,-1)(6,6)}% +%{\psframe[fillstyle=solid, fillcolor=lightgray](-1,-1)(6,6)}% \end{pspicture} \end{center} diff --git a/Master/texmf-dist/dvips/pst-bspline/pst-bspline.pro b/Master/texmf-dist/dvips/pst-bspline/pst-bspline.pro new file mode 100644 index 00000000000..03cefb849ef --- /dev/null +++ b/Master/texmf-dist/dvips/pst-bspline/pst-bspline.pro @@ -0,0 +1,68 @@ +% $Id: pst-bspline.pro 2011-07-30 23:45:00Z michael $ +%% +%% PostScript prologue for pst-bspline.tex. +%% Version 1.00, 2011/07/30. +%% +%% This program can be redistributed and/or modified under the terms +%% of the LaTeX Project Public License Distributed from CTAN archives +%% in directory macros/latex/base/lppl.txt. +% +% +% +tx@Dict begin +% +% numerically stable cubic root finding +% +/cubic_roots {% solve c3*t^3+c2*t^2+c1*t+c0==0 +% call with c3 c2 c1 c0 cubic_root, return solution array roots, numroots, zroot on stack +% zroot is either (a) 2, if no solution in [0,1], or +% (b) a solution in [0,1]. + 15 dict begin % all variables are local + /numroots 0 def /roots 3 array def /zroot 2 def /epsilon 1e-6 def % + /c0 ED /c1 ED /c2 ED /c3 ED % + c3 abs epsilon lt { %quadratic case + c2 abs epsilon le { c1 abs epsilon ge { % + roots 0 c0 c1 div neg put /numroots 1 def} if }% + { %c2 neq 0 + /bb c1 dup mul def % + /q bb 4 c0 c2 mul mul sub def % + q abs epsilon lt { roots 0 c1 c2 -2 mul div put /numroots 1 def } % + { q 0.0 gt { % in fact, q>= epsilon + /q q sqrt def % + c1 0.0 lt { /q q neg def } if % + /q c1 q add -2 div def % + roots 0 q c2 div put /numroots 1 def % know |c2|>=epsilon + q abs epsilon ge { roots numroots c0 q div put /numroots numroots 1 add def } if % + } if % + } ifelse } ifelse } % + {% true cubic + /c2 c2 c3 div def /c1 c1 c3 div def /c0 c0 c3 div def % normalize + /Q c2 dup mul 3 c1 mul sub 9 div def /QQQ Q dup dup mul mul def % + /R c2 dup dup mul mul 2 mul c2 c1 9 mul mul sub 27 c0 mul add 54 div def % + /RR R dup mul def % + /c2 c2 3 div def % + RR QQQ lt {% + /theta R QQQ sqrt div Acos 3 div def % in degrees + /numroots 3 def % + /r2 Q sqrt -2 mul def % + roots 0 r2 theta cos mul c2 sub put % + roots 1 r2 theta 120 add cos mul c2 sub put % + roots 2 r2 theta 120 sub cos mul c2 sub put % + }{% One or two real roots + /r0 0 def % + /A R abs RR QQQ sub sqrt add 1 3 div exp neg def % + A abs epsilon gt { % + R 0.0 lt { /A A neg def } if % + /r0 A Q A div add def } if % + roots 0 r0 c2 sub put /numroots 1 def % + A dup mul Q sub abs A abs epsilon mul lt {% + roots numroots A c2 add neg put /numroots numroots 1 add def } if % + } ifelse % + } ifelse % + 0 1 numroots 1 sub {/j ED roots j get dup 2 mul 1 sub abs 1 le { /zroot ED } if } for % + roots numroots zroot %leave these three items on stack + end } def % +% +end % tx@Dict +% +% END pst-bspline.pro diff --git a/Master/texmf-dist/tex/generic/pst-bspline/pst-bspline.tex b/Master/texmf-dist/tex/generic/pst-bspline/pst-bspline.tex index eaea89f9b77..a16112455a1 100644 --- a/Master/texmf-dist/tex/generic/pst-bspline/pst-bspline.tex +++ b/Master/texmf-dist/tex/generic/pst-bspline/pst-bspline.tex @@ -8,13 +8,15 @@ \ifx\PSTricksLoaded\endinput \else\input pstricks \fi \ifx\PSTnodeLoaded\endinput \else\input pst-node \fi \ifx\PSTXKeyLoaded\endinput \else\input pst-xkey \fi -\def\fileversion{1.41} -\def\filedate{2010/10/19} +\def\fileversion{1.44} +\def\filedate{2011/07/29} \message{`pst-bspline' v\fileversion, \filedate\space Bspline routines for pstricks (ms)} % \edef\TheAtCode{\the\catcode`\@} \catcode`\@=11\relax \pst@addfams{pst-bspline} +\pstheader{pst-bspline.pro} + \SpecialCoor %\newcount\pst@args%used in several macros--now defined in pst-node.tex @@ -152,12 +154,12 @@ \advance\bsp@cntB by \@ne% \psbezier[arrows=-\bsp@arrowB,showpoints=false](\bsp@root S\the\bsp@cntA)% (\bsp@root R\the\bsp@cntA)(\bsp@root L\the\bsp@cntB)(\bsp@root S\the\bsp@cntB)% - \ifPst@showframe \psdot[linecolor=red](\bsp@root L\the\bsp@cntB) \fi% +% \ifPst@showframe \psdot[linecolor=red](\bsp@root L\the\bsp@cntB) \fi% \fi% end \ifbsp@closed -\ifPst@showframe% - \psdot[linecolor=red](\bsp@root R0)% - \psdot[linecolor=red](\bsp@root L\the\bsp@args)% -\fi% +%\ifPst@showframe% +% \psdot[linecolor=red](\bsp@root R0)% +% \psdot[linecolor=red](\bsp@root L\the\bsp@args)% +%\fi% \ifshowpoints% \multido{\i=0+1}{\bsp@args}{\psdot(\bsp@root S\i)}% \fi% @@ -247,7 +249,7 @@ \fi% \newcount\top@ndx \top@ndx=\top@mone% \advance\top@ndx by \@ne%number of nodes to interpolate -\ +%\ \newcount\top@mtwo \top@mtwo=\top@mone \advance\top@mtwo\m@ne% % After copying S0 to S101, \top@ndx, \top@mone, \top@mtwo are top index, top index-1, top index-two---101, 100, 99 in the example \make@mcoeff{\the\top@ndx}% @@ -307,12 +309,11 @@ \multiply\np@cnt \tw@\advance\np@cnt \tw@% count of points in array \pstVerb{ gsave tx@Dict begin % /psxu \pst@number\psxunit\space def /psyu \pst@number\psyunit\space def % - /uratio psyu psxu div def % so that perp to a, b is -b*uratio a + /uratio psyu psxu div dup mul def % so that perp to a, b is -b*uratio, a /nseg #2 def /nplotpt \psk@plotpoints\space def % /clipary #2 nplotpt mul 4 mul 4 add array def % /lindex 2 def /uindex \the\ary@max\space 1 sub def % /dt 1 \psk@plotpoints\space div def % -% /halfthck #3 2 div def % end grestore }% \multido{\iA=0+1,\iB=1+1}{#2}{% % pass control points of this segment to PostScript variables @@ -320,7 +321,6 @@ gsave tx@Dict begin % STV CP T \psGetNodeCenter{#1\iA}\space \psGetNodeCenter{#1BR\iA}\space \psGetNodeCenter{#1BL\iB}\space \psGetNodeCenter{#1\iB}\space % /bez@1.x #1\iA.x def /bez@1.y #1\iA.y def %initial point on segment - %(START) = bez@1.x = bez@1.y = SB1.x = % /bez@2.x #1BR\iA.x bez@1.x sub def %adjusted control points (less init pt) /bez@2.y #1BR\iA.y bez@1.y sub def % /bez@3.x #1BL\iB.x bez@1.x sub def % @@ -340,9 +340,9 @@ /Func % position ( bez@3x t mul bez@2x add t mul bez@1x add t mul bez@1.x add psxu mul % bez@3y t mul bez@2y add t mul bez@1y add t mul bez@1.y add psyu mul ) cvx def % -%/FuncT % tangent -% ( bez@1x t bez@2xT mul add t t bez@3xT mul mul add % -% bez@1y t bez@2yT mul add t t bez@3yT mul mul add ) cvx def +% /FuncT % tangent +% ( bez@2xT t bez@3xT mul add t mul bez@1x add % +% bez@2yT t bez@3yT mul add t mul bez@1y add ) cvx def /FuncN % unit normal times delta ( bez@2yT t bez@3yT mul add t mul bez@1y add uratio mul neg bez@2xT t bez@3xT mul add t mul bez@1x add 2 copy Pyth dup % @@ -363,7 +363,7 @@ /lindex lindex 2 add def /uindex uindex 2 sub def ){tmp@P}% }% end multido \i }% end multido \iA -% if periodic, we have to adjust 2 points so as not too leave a wege in the +% if periodic, we have to adjust 2 points so as not too leave a wedge in the % clipping region. We have to set Q_{nk} to Q_0 and R_{nk} to R_0 % R_{nk} is at position 2*nk, 2*nk+1 and Q_{nk} is at the next pair %\ifbsp@per % @@ -393,5 +393,138 @@ \fi% }% \ignorespaces}% +% +\def\bsp@setup#1#2#3#4{% +%#1=bsp root, #2=num #3=\top@ndx, #4=top@ndx-1, #4 + \pstVerb{tx@Dict begin gsave STV CP T /bsp@desc #2 array def }% +% \def\num{#2} + \multido{\iA=#4+-1,\iB=#3+-1}{#2}{%\show\num + \pstVerb{% + \psGetNodeCenter{#1S\iA}\space \psGetNodeCenter{#1R\iA}\space \psGetNodeCenter{#1L\iB}\space \psGetNodeCenter{#1S\iB}\space % + /bez@0x #1S\iA.x def /bez@0y #1S\iA.y def %initial point on segment + /bez@1x #1R\iA.x bez@0x sub 3 mul def % for position--w1=3z1 + /bez@1y #1R\iA.y bez@0y sub 3 mul def + /bez@2x #1L\iB.x bez@0x sub #1R\iA.x bez@0x sub 2 mul sub 3 mul def % w2=3(z2-2z1) + /bez@2y #1L\iB.y bez@0y sub #1R\iA.y bez@0y sub 2 mul sub 3 mul def % w2=3(z2-2z1) + /bez@3x #1S\iB.x bez@1x add #1L\iB.x 3 mul sub bez@0x 2 mul add def % w3=z3+3z1-3z2 + /bez@3y #1S\iB.y bez@1y add #1L\iB.y 3 mul sub bez@0y 2 mul add def % w3=z3+3z1-3z2 + bsp@desc \iA\space mark bez@2y 2 mul bez@3y 3 mul bez@2x 2 mul bez@3x 3 mul bez@0y % + bez@1y bez@2y bez@3y bez@0x bez@1x bez@2x bez@3x ] put }% + }% end multido + \pstVerb{ grestore end }% closed tx@Dict, which contains array named bsp@desc +}% bsp@setup +\def\bspcurvepointsE{\pst@object{bspcurvepointsE}}% +\def\bspcurvepointsE@i#1#2#3{\bspcurvepoints@ii{#1}{#2}{E}{#3}}% +\def\bspcurvepoints{\pst@object{bspcurvepoints}}% +\def\bspcurvepoints@i#1#2#3{\bspcurvepoints@ii{#1}{#2}{}{#3}}% +\def\bspcurvepoints@ii#1#2#3#4{{%optional [plotpoints=xx] +% #1=bsp root,#2=maxindex,#3=E/{},#4=root name for new PS arrays, + \pst@killglue% + \newcount\bsp@numndx + \bsp@numndx=#2 \relax% + \ifx#3E\relax + \advance \bsp@numndx \m@ne \edef\top@ndx{\the\bsp@numndx} + \advance \bsp@numndx \m@ne \edef\topm@ndx{\the\bsp@numndx}% + \else% + \edef\top@ndx{\the\bsp@numndx}% + \pst@cntc=\bsp@numndx\advance\pst@cntc \m@ne% + \edef\topm@ndx{\the\pst@cntc}% + \fi% + \pst@cntb=\bsp@numndx %\advance\pst@cntb \@ne\relax% + % set up the bsp ps array + \edef\cmd{\noexpand\bsp@setup{#1}{\the\bsp@numndx}{\top@ndx}{\topm@ndx}}\cmd% + \use@par% + \pst@cntc=\psk@plotpoints\relax%\psk@plotpoints=plotpoints-1 + \pst@cnta=\pst@cntc \multiply\pst@cnta by \pst@cntb% + \edef\bsp@nsegs{\the\bsp@numndx}%\show\bsp@nsegs% + \advance\pst@cnta by \@ne\relax%=(plotpoints-1)*nsegs+1 + \edef\@arraysize{\the\pst@cnta}% +% \show\@arraysize + \pstVerb{ tx@Dict begin % + /psxu \pst@number\psxunit\space def /psyu \pst@number\psyunit\space def % + /unitratio \pst@number\psyunit \pst@number\psxunit div def % + /unitratiosq unitratio dup mul def % + /dt 1 \psk@plotpoints\space div def % + /#4.X \@arraysize\space array def % + /#4.Y \@arraysize\space array def % + /#4Delta.X \@arraysize\space array def % + /#4Delta.Y \@arraysize\space array def % + /#4Normal.X \@arraysize\space array def % + /#4Normal.Y \@arraysize\space array def % + /theseg 0 def %\the\bsp@numndx\space 1 sub def % + bsp@desc theseg get % the first segment + /cnt 1 def % counter for arrays + dup dup dup 8 get psxu mul 4 1 roll 4 get psyu mul 3 1 roll % + 9 get exch 5 get %4 copy = = = = % initial x, y, x', y' + unitratiosq mul neg #4Normal.X 0 3 -1 roll put #4Normal.Y 0 3 -1 roll put % + 2 copy #4.Y 0 3 -1 roll put #4.X 0 3 -1 roll put % + /priory ED /priorx ED % arrays now initialized + \bsp@nsegs\space {% repeat nsegs times + bsp@desc theseg get aload pop /x3 ED /x2 ED /x1 ED /x0 ED % + /y3 ED /y2 ED /y1 ED /y0 ED % + /xT3 ED /xT2 ED /yT3 ED /yT2 ED % + /Func ( x3 t mul x2 add t mul x1 add t mul x0 add psxu mul % + y3 t mul y2 add t mul y1 add t mul y0 add psyu mul ) cvx def % + /FuncN ( yT2 t yT3 mul add t mul y1 add unitratiosq mul neg % + xT2 t xT3 mul add t mul x1 add ) cvx def % + /theseg theseg 1 add def % + /j 1 def \psk@plotpoints\space {% repeat for each plotpt + /t j dt mul def Func 2 copy 2 copy FuncN % x y x y x y xN yN + #4Normal.Y cnt 3 -1 roll put % + #4Normal.X cnt 3 -1 roll put % + #4.Y cnt 3 -1 roll put % + #4.X cnt 3 -1 roll put % x y x y on stack + priory sub #4Delta.Y cnt 3 -1 roll put % + priorx sub #4Delta.X cnt 3 -1 roll put % x y on stack + /priory ED /priorx ED /j j 1 add def /cnt cnt 1 add def } repeat % + } repeat %#4.Y == % + end }% end pstVerb + \pst@cnta=\@arraysize \relax\advance\pst@cnta \m@ne % + \expandafter\xdef \csname #4pointcount\endcsname {\the\pst@cnta}% + \typeout{Created points #40 .. #4\the\pst@cnta}% +}\ignorespaces}% +\def\bspFnNode#1#2#3#4{% +% #1=root name for B-spline control points, #2=top index +% #3=x value, #4=name of node to place at (x,f(x)) +% This works only for a bspline function graph, not a general bspline curve +\pnode(! bsp@desc length /n ED % + /x #3 def % + x bsp@desc 0 get 8 get dup /xt ED lt { /x xt def } if % + x bsp@desc n 1 sub get 8 4 getinterval aload pop add add add %endpt of last segment + dup /xt ED gt { /x xt def } if % + /j 0 def % + n {% repeat + x bsp@desc j get 8 get dup /xt ED le { exit } if /j j 1 add def % + } repeat % + j 0 gt { /j j 1 sub def } if %j is index of bezier segment containing x + bsp@desc j get dup dup dup % + 11 get exch 10 get 4 2 roll 9 get exch 8 get x sub cubic_roots % + /t ED pop pop % + t 1 gt { /t 1 def } if % zroot is the t value at which x=x(t) + x bsp@desc j get 4 4 getinterval aload pop % leaves y0, y1, y2, y3 on stack + t mul add t mul add t mul add % x y now on stack + ){#4}% +}% end bspFnNode +% +\def\bspNode#1#2#3#4{% +%src maxindex t target +\pnode(! bsp@desc length /n ED % + /t #3 def % + t 0 lt { /t 0 def } if % + t n gt { /t n def } if % clamp t to [0,n] + /j t cvi def j n eq { /j n 1 sub def } if % + /t t j sub def % t in [0,1] + bsp@desc j get dup % + 8 4 getinterval aload pop t mul add t mul add t mul add % desc[[j]] x(t) + exch 4 4 getinterval aload pop t mul add t mul add t mul add % x(t) y(t) + ){#4}% +}% end bspNode +% +\def\bspcurvenodes#1#2{% +%#1= basename for points on curve, #2=basename for nodes +\multido{\iA=0+1}{\csname #1pointcount\endcsname}{% +\pnode(! #1.X \iA\space get #1.Y \iA\space get ){#2\iA}}% +}% +% \catcode`\@=\TheAtCode\relax \endinput
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/pst-bspline/pst-bspline.sty b/Master/texmf-dist/tex/latex/pst-bspline/pst-bspline.sty index 1dabf7aafc8..07f3483441e 100644 --- a/Master/texmf-dist/tex/latex/pst-bspline/pst-bspline.sty +++ b/Master/texmf-dist/tex/latex/pst-bspline/pst-bspline.sty @@ -1,5 +1,5 @@ \ProvidesPackage{pst-bspline} - [2010/10/19 v1.41 LaTeX wrapper for pst-bspline (MS)] + [2011/06/13 v1.42 LaTeX wrapper for pst-bspline (MS)] \input{pst-bspline} \ProvidesFile{pst-bspline.tex} [\filedate\space \fileversion\space `pst-bspline' (ms)] |