The pshacks package^{∗}

Andrew D. Lewis

1998/06/22

1 Introduction

The package pshacks is a supplement to the PSTricks macros written by Timothy Van Zandt from Princeton (tvz@Princeton.edu). These macros are available via anonymous ftp from any CTAN site. The additions have been along the following lines.

1. Make the commands less cryptic.

2. Add some features which I find useful.

3. Make it easier to create Encapsulated PostScript figures.

This version of pshacks works with ‘v93a/b-97 patch 3’ of PSTricks, and will not work with earlier versions.

For those unfamiliar with PSTricks, it is a package which allows the inclusion of PostScript drawings in your file. In its most simple form, PSTricks does not create a PostScript file, but rather adds a \special hook with a bunch of enclosed PostScript commands for the dvi to PostScript converter you are using. With PSTricks comes an environment called pspicture which works a little like an extended L^{A}TEX picture environment. The commands in pshacks are designed to work within this environment.

PSTricks also has facilities for creating Encapsulated PostScript files from the drawing macros. pshacks defines a new environment, psdraw, which facilitates this capacity.

In this manual I shall attempt to briefly outline the features of pshacks. For a more thorough discussion of PSTricks, see the manual which is included in this distribution. A full understanding of PSTricks will greatly enhance your capabilities with pshacks.

2 How to Access the pshacks Commands

To begin drawing a picture, use the pspicture environment. It has arguments like

∗This file has version number v2.0a, last revised 1998/06/22.

    \begin{pspicture}*[ref ](x_{0},y_{0})(x_{1},y_{1})

where (x_{0}, y_{0}) is the coordinate of the lower left corner and (x_{1}, y_{1}) is the coordinate of the upper right corner. These coordinates will be used as a reference for any moving around you do (just as in the L^{A}TEX picture environment), and will also be the size of TEX box that will be created (i.e. things overflowing this box will not go into the computation of its size). The units used in pshacks are cm. Although PSTricks allows changing these units, I recommend against it since I have not tested any of the macros with different units and they may screw up in subtle ways. If you use the command \begin{pspicture}* instead of \begin{pspicture}, the drawing will be clipped. Thus everything outside the specified box will not appear. The optional argument ref gives the reference baseline for the picture.

Inside the confines of the pspicture environment, you may use the macros described in the remainder of this manual. Thus a typical figure created by pshacks figure may look like:

    \begin{pspicture}(x_{0},y_{0})(x_{1},y_{1})

           .

pshacks commands

           .
    \end{pspicture}

It is possible at any time to use any of the PSTricks macros. In particular, it may be useful to use the \pscustom command to make graphics not available with pshacks macros. Also helpful is the \psset command which allows you to set certain parameters for the plot. Most of the time, using PSTricks macros will not cause a problem, but you should be aware that there is an interface between pshacks and PSTricks that you may be overlooking.

3 Coordinates

As mentioned above, pshacks uses cm as the default unit, and it is recommended that you stick to this. When you first invoke pspicture you are placed at the coordinate (0, 0) and from there you can go where you like.

To move to a coordinate you have several options:

\move(x,y): This will move you to the absolute coordinate (x, y).

\relmove(dx,dy): This will move you from your current location a relative displacement (dx, dy).

\rmove{r}{θ}: This will move a distance r along a line with angle θ.

The “r” means ray.

When drawing graphics objects, the current location may or may not change. As a general rule, the location will change if you are drawing a line from the current position to a new position and will otherwise remain unchanged. Exceptions will be pointed out.

4 Optional Arguments

In usual L^{A}TEX fashion, optional arguments are available. In this section we give the convention for these optional arguments unless otherwise stated. Following commands which draw curves of any sort (a curve being a line, a spline, a circle, etc.) there is an optional *. If this is present, the curve will be drawn dashed. If is is absent, the line style will be the current line style. The default is solid lines.

For commands which draw curves from one point to another, there is an optional command enclosed in [] which gives the arrow type. Some possibilities are - (no arrows), <- (an arrow at the beginning of the line), -> (an arrow at the end of the line), and <-> (arrows at both ends). There are other possibilities which are outlined in the PSTricks manual. The default is -.

For graphics objects which can be filled, one can set the fill level with an optional argument contained in []. Values for the fill level are between 0 and 1 with 0 being white and 1 being black. The fill style may be adjusted with PSTricks commands. The default fill style is solid. If this optional argument is not present, the object is not filled which is different than being filled to level 0.

For positioning text and boxes, there are optional arguments enclosed in [] which say which corner of the box should be positioned at the current position. The possibilities are l, lb, lt, r, rb, rt, b, and t. As is usual with L^{A}TEX, l means left, r means right, b means bottom, and t means top. The default is for the object to be centred.

5 Lines

pshacks offers several ways to draw a line. All will draw a line which commences from your current location and updates the current position to the end of the line. Note that the commands here mirror the moving commands.

\vec*[arr](x,y): Draws a line to the point (x, y) with arrow style arr.

\relvec*[arr](dx,dy): Draws a line with relative coordinates (dx, dy) with arrow style arr.

\rvec*[arr]{r}{θ}: Draws a line of length r at an angle θ with arrow style arr.

In all cases the * is optional, and if it is present, the line is drawn dashed. The argument arr is also optional and specifies the arrow style for the line. The command \vec overrides the original L^{A}TEX command with this name. This old command is still available under the name \oldvec.

The line width is modified with the command \scalelines. To scale the line width you type

    \scalelines{factor}

where factor is a number reflecting how much you want to scale the default line width. The default line width is 0.8pt. If you like you can adjust the default line width with PSTricks macros. However, the command \scalelines will still scale the original default line width.

The line style is adjustable as in PSTricks. pshacks provides the command \dashedlines which sets the line style to dashed.

Here is an example of how lines may be drawn. The code

 \begin{center}
 \begin{pspicture}(-1.268,-2.719)(3,3)
 \vec*(3,0)
 \move(0,0)\scalelines{2}\relvec(1.5,1.5)
 \move(0,0)\scalelines{3}\rvec*{3}{90}
 \move(0,0)\scalelines{4}\rvec[->]{3}{245}
 \end{pspicture}
 \end{center}
 \end{center}

produces the drawing

Note that the arrow size scales with the line width.

6 Circles, Ellipses, and Arcs

None of the commands in this section change the current position.

For drawing circles pshacks offers the command \cir which is used as follows:

\cir*[fill]{r}: Draws a circle centred at the current location of radius r with fill density fill.

The * is optional and, if present, sets the line style for the circle to dashed. As usual in L^{A}TEX, the arguments in square brackets, [], are optional. The value of fill must be between 0 and 1 with 0 being white and 1 being black.

To illustrate the circle capacities, the code

 \begin{center}
 \begin{pspicture}(-1,-1)(2,1)
 \cir[0.4]{1}\relmove(0.5,0)\cir*[0]{1}\relmove(0.5,0)\cir{1}
 \end{pspicture}
 \end{center}

makes the drawing

To draw a wedge use the command \pswedge:

\pswedge*[fill]{rad}(θ_{1},θ_{2}): Draws a wedge at the current location filled to fill, of radius rad, and between angles θ_{1} and θ_{2}.

For example, the code

 \begin{center}
 \pswedge[0.3]{3}(45,135)
 \end{center}

gives the picture

To draw an ellipse use the command \ellip:

\ellip*[fill]{radx}{rady}{θ}: Draws an ellipse centred at the current location with radius in the x-direction of radx, radius in the y-direction of rady. The x-axis of the ellipse makes an angle of θ degrees with the reference x-axis, and the ellipse is filled to density fill.

As usual for these things, the * is optional and gives dashed lines if present. The ellipse was produced by the commands

 \begin{center}
 \begin{pspicture}(-2.598,-1.5)(2.598,1.5)
 \ellip{0.5}{3}{120}
 \end{pspicture}
 \end{center}

To draw the arc of a circle use the command \arc:

\arc*[arr]{r}(θ_{1},θ_{2}): Draws a counterclockwise arc of radius r between the angles θ_{1} and θ_{2} with arrow type arr.

The usual thing is true for the star and []. To get an arc

type

 \begin{center}
 \begin{pspicture}(-1,-1)(1,1)
 \arc*[<->]{1}(0,-45)
 \end{pspicture}
 \end{center}

It is also possible to draw elliptical arcs with the command \elliparc.

\elliparc*{radx}{rady}(θ_{1},θ_{2}){ψ}: Draws the arc of an ellipse centred at the current location with x-radius radx and y-radius rady with the x-axis of the ellipse making an angle ψ with the horizontal. The angles θ_{1} and θ_{2} have something to to with the extent of the arc and work something like the arguments for \arc.

Notice that this description is a bit vague about θ_{1} and θ_{2}. This is because they don’t work like you’d want them to. Some hacking is needed to make them work in some circumstances.

The following example illustrates that the angles θ_{1} and θ_{2} are not what one would naively expect. The code

 \begin{center}
 \begin{pspicture}(0,-2.5)(2.121,2.5)
 \rvec{3}{45}\move(0,0)\rvec{3}{-45}
 \move(0,0)\elliparc{2}{3}(-45,45){0}
 \end{pspicture}
 \end{center}

produces the drawing

I also have found use for a “centre of gravity” symbol. The syntax for this is \cengrav{r} where r is the radius of the symbol which looks like:

7 Boxes and Polygons

With pshacks you may draw a box with a given orientation of a given size. Use

the commands \drawrbox and \drawhbox.

\drawrbox*{θ}[fill](lenx,leny)[arg]: Draws a box of dimensions lenx × leny and orientation θ. The box is filled to intensity fill. The box is positioned according to arg. See Section 4 for the possibilities.

\drawhbox*[fill](lenx,leny)[arg]: Draws a box whose orientation is 0. The box is positioned according to arg. See Section 4 for the possibilities.

Here is an illustration of how boxes are drawn. The code

 \begin{center}
 \begin{pspicture}(0,0)(5,4)
 \cir[1]{0.1}\drawrbox*{30}[0.1](2,3)[lb]
 \move(5,4)\cir[1]{0.1}\drawhbox(2,3)[rt]
 \end{pspicture}
 \end{center}

produces

There are also related commands for making boxes with rounded corners.

\drawrcbox*{θ}[fill](lenx,leny){r}[arg]: Draws a box with corners radiused to r of dimensions lenx × leny and orientation θ. The box is filled to intensity fill. The box is positioned according to arg. See Section 4 for the possibilities.

\drawhcbox*[fill](lenx,leny){r}[arg]: Draws a box with corners radiused to r whose orientation is 0. The box is positioned according to arg. See Section 4 for the possibilities.

We illustrate this with the code

 \begin{center}
 \begin{pspicture}(0,0)(5,4)
 \cir[1]{0.1}\drawrcbox{30}[0.1](2,3){0.3}[lb]
 \move(5,4)\cir[1]{0.1}\drawhcbox(2,3){1}[rt]
 \end{pspicture}
 \end{center}

which produces

Polygons are also possible.

\polygon*[fill](x_{0},y_{0})...(x_{n},y_{n}): Draws a polygon with vertices (x_{0}, y_{0})… (x_{n}, y_{n}) filled to level fill.

The * is, as usual, the option argument for dashed lines. The user should be aware that \polygon does not affect the current location.

The code

 \begin{center}
 \begin{pspicture}(0,0)(4,2)
 \polygon[0.2](0,0)(0,2)(4,0)(4,2)\move(4,2)
 \end{pspicture}
 \end{center}

gives the polygon

8 Arrowed Objects

I use arrows a lot in my figure making so I have written some convenient arrow macros. These are as follows:

\rarrow{θ}: Makes an arrow with its head at the current location pointing in the direction θ.

\rdblaveclbl*[arr]{r}{θ}{text}{width}: Makes a double arrowed line of length r from the current location in the direction θ. The label text is placed in the middle of the line in a gap of width width.

\dblarclbl*[]{r}(θ_{1},θ_{2}){text}{ϕ}: Makes a counterclockwise arc of radius r between the angles θ_{1} and θ_{2}. There is an arrow at each end and the label text is in the middle of the arc in a gap of angular width ϕ. The angles θ_{1} and θ_{2} must be numbers with absolute value less than or equal to 360.

It is possible to make changes in the arrows with PSTricks macros. See the documentation for assistance.

Here is a demonstration of the arrow commands. The code

 \begin{center}
 \begin{pspicture}(0,-1)(5.707,1.732)
 \rarrow{75}
 \move(1,0)\rdblaveclbl{2}{120}{$x$}{0.35}
 \move(5,0)\dblarclbl*{1}(45,-45){$\psi$}{30}
 \move(3,0)\dblarclbl[<-]{1}(45,-45){$\psi$}{30}
 \end{pspicture}
 \end{center}

produces the drawing

x  ψ  ψ

9 Bézier Curves

With the pshacks macros are some facilities for making so-called Bézier curves. A Bézier curve is determined by specifying four points, say (x_{1}, y_{1}), (x_{2}, y_{2}), (x_{3}, y_{3}), (x_{4}, y_{4}). Now imagine the following construction. Let v_{1} be a vector attached to (x_{1}, y_{1}) which points to (x_{2}, y_{2}) and let v_{2} be a vector attached to (x_{4}, y_{4}) which points to (x_{3}, y_{3}). A Bezier curve for these four points is a cubic polynomial which joins (x_{1}, y_{1}) with (x_{4}, y_{4}) and is tangent to v_{1} at (x_{1}, y_{1}) and tangent to v_{2} at (x_{4}, y_{4}). The points (x_{2}, y_{2}) and (x_{3}, y_{3}) are called control points. The following picture tells the story.

To make Bézier curves with pshacks, use the command \cvec.

\cvec*[arr](x_{0},y_{0})(x_{1},y_{1})(x_{2},y_{2})(x_{3},y_{3}): Draws a Bézier curve from (x_{0}, y_{0}) to (x_{3}, y_{3}) with control points (x_{1}, y_{1}) and (x_{2}, y_{2}) and arrow style arr.

The above Bézier curve was generated with the text

 \begin{center}
 \begin{pspicture}(0,0)(6,2)
 \cvec(0,0)(2,2)(6,2)(4,0)
 \move(0,0)\vec*(2,2)\move(4,0)\vec*(6,2)
 \end{pspicture}
 \end{center}

The user should be warned that \cvec does not change your current position.

10 Splined Curves

For drawing splines pshacks has several available macros.

\openspline*[arr](x_{0},y_{0} )...(x_{n},y_{n}): Draws a splined curve through the points (x_{0}, y_{0})… (x_{n}, y_{n}) with arrow style arr.

\espline*[arr](x_{0},y_{0})...(x_{n},y_{n}): Draws a splined curve through the points (x_{1}, y_{1})… (x_{n−1}, y_{n−1}) with arrow style arr. The points (x_{0}, y_{0}) and (x_{n}, y_{n}) go into the computation of the ends of the spline.

\closedspline*[fill](x_{0},y_{0})...(x_{n},y_{n}): Draws a closed spline though the points (x_{0}, y_{0})… (x_{n}, y_{n}) with fill level fill.

None of the spline commands change the current position. The optional * changes the line style to dashed.

First we illustrate how to draw an open spline. The commands

 \begin{center}
 \begin{pspicture}(0,-2)(4,2)
 \cir[1]{0.1}
 \move(2,2)\cir[1]{0.1}
 \move(4,0)\cir[1]{0.1}
 \move(2,-2)\cir[1]{0.1}
 \openspline[->](0,0)(2,2)(4,0)(2,-2)
 \end{pspicture}
 \end{center}

will produce the spline

When making a closed spline you may choose to fill it or just draw the border. The options are illustrated by the commands

 \begin{center}
 \begin{pspicture}(5,-3)(13,3)
 \move(5,0)\cir[1]{0.1}
 \move(6,3)\cir[1]{0.1}
 \move(8,-3)\cir[1]{0.1}
 \closedspline*[0.2](5,0)(6,3)(8,-3)
 \move(9,0)\cir[1]{0.1}
 \move(11,2)\cir[1]{0.1}
 \move(13,0)\cir[1]{0.1}
 \move(11,-2)\cir[1]{0.1}
 \closedspline(9,0)(11,2)(13,0)(11,-2)
 \end{pspicture}
 \end{center}

which produce the splines

The \espline command is useful for making a spline which has different line types but which needs to retain its smoothness. To illustrate this, the following code produces the spline

 \begin{center}
 \begin{pspicture}(0,-1)(7,1)
 \espline(-1,-1)(0,0)(1,1)(2,0)(3,-1)(4,0)
 \espline*(2,0)(3,-1)(4,0)(5,1)(6,0)(7,-1)
 \end{pspicture}
 \end{center}

produces the spline

11 Modifying Optional Fills

We saw that many of the graphics objects discussed above have an optional fill level specified by an argument like [fill]. It is also possible to modify some of the parameters used to do the filling with the use of pshacks commands. The first thing you may want to do is fill with colours (the user will forgive while I proceed to use “colour” to mean the usual thing, and “color” to refer to anything having to do with talking to the computer…). To do so one places the object to be filled inside a fillcolor environment and specifies the desired fill colour as an argument. The colours available are the ones given with pstricks plus any that you define yourself using pstrick macros. You may also wish to change the fill style to something other than solid. This is done with the fillstyle environment which takes as an option one of the fill styles allowed by pstricks. The three circles

were made with the macros

 \begin{pspicture}(-3,-1)(3,1)
 \move(-2,0)
 \begin{fillstyle}{vlines}
 \begin{fillcolor}{blue}
 \cir[0.25]{1}
 \end{fillcolor}
 \end{fillstyle}
 \move(0,0)
 \begin{fillstyle}{crosshatch*}
 \begin{fillcolor}{red}
 \cir[0.1]{1}
 \end{fillcolor}
 \end{fillstyle}
 \move(2,0)
 \cir[0.5]{1}
 \end{pspicture}
 \end{center}

The value of the fill level argument is irrelevant for the objects with colours specified. However, it must be present to indicate that you will be filling the object with the current colour. The leftmost circle has no blue shading because the fill style vlines does not specify shading (see pstricks for this).

If for some reason (you are not using a colour printer, for example) you want to switch off the colours, you may do so by specifying the nocolors option when you load pshacks. In this case, the optionally filled objects will be filled to the level specified by the fill level argument.

12 Text

With pshacks it is possible to place TEXt anywhere in your figure you wish. It also offers the possibility of rotating the text. The following commands are available:

\htext[arg]{text}: This places horizontal text, text, at the current location with positioning specified by arg. For possible values of arg, see Section 4.

\rtext{θ}[arg]{text}: This places text, text, at the current location with orientation θ with positioning specified by arg. For possible values of arg, see Section 4.

\vtext[arg]{text}: This places vertical text, text, at the current location with positioning specified by arg. For possible values of arg, see Section 4.

Note that the position arguments work differently that for positioning boxes with

\drawrbox.

The following code

 \begin{center}
 \begin{pspicture}(0,-1)(4,0.5)
 \cir[1]{0.05}\htext[lb]{htext}
 \move(2,0)\cir[1]{0.05}\rtext{50}{rtext}
 \move(4,0)\cir[1]{0.05}\vtext[r]{vtext}
 \end{pspicture}
 \end{center}

produces

htext  rtext  vtext

13 Saving Positions

Sometimes it is handy to be able to record a location for future use. There are two commands available for this.

\savecurrpos(x,y): Saves the current position which may later be referenced by

     (\usecoor{x},\usecoor{y}).

14 Scaling

Scaling can be done absolutely or relatively. The commands are

\setscale{scale}: Scales the overall figure by scale. If placed before \begin{pspicture}, the units in the argument will also be scaled.

\setrelscale{factor}: Sets the scale to the current scale multiplied by factor.

Here is an illustration of scaling. The figure

Text1  Text2  Text3

was produced by the code

 \begin{center}
 \setscale{0.5}
 \begin{pspicture}(-2.5,-2.5)(2.5,2.5)
 \cir{2.5}\htext{Text1}
 \end{pspicture}
 \setscale{0.25}
 \begin{pspicture}(-2.5,-2.5)(2.5,2.5)
 \cir{2.5}\htext{Text2}
 \end{pspicture}
 \setrelscale{2}
 \begin{pspicture}(-2.5,-2.5)(2.5,2.5)
 \cir{2.5}\htext{Text3}
 \end{pspicture}
 \end{center}

Notice that the text does not scale. I consider this to be a big bonus, but you may not.

15 Segments

Sometimes it is useful to have a section of a picture with its own coordinate system and its own scaling. This is made possible with the segment environment. Within this environment, the coordinate system is refreshed to (0, 0) and any movement is made with respect to this new origin. If you’d like to scale what is inside the segment, invoke either of the following two commands right after the segment starts.

\setsegscale{scale}: Scales the segment to scale.

\setrelsegscale{factor}: Sets the segment scale to the current segment scale multiplied by factor.

If do not scale the segment at the beginning, but choose to do so in the middle, I cannot predict what will happen. Chances are it will not be pretty, however.

The code

 \begin{center}
 \begin{pspicture}(-1.268,-2.719)(7,3)
 \vec*(3,0)

 \move(0,0)\scalelines{2}\relvec(1.5,1.5)
 \move(0,0)\scalelines{3}\rvec*{3}{90}
 \move(0,0)\scalelines{4}\rvec[->]{3}{245}
 \move(4,0)\scalelines{1}
 \begin{segment}
 \setsegscale{0.5}
 \vec*(3,0)
 \move(0,0)\scalelines{2}\relvec(1.5,1.5)
 \move(0,0)\scalelines{3}\rvec*{3}{90}
 \move(0,0)\scalelines{4}\rvec[->]{3}{245}
 \end{segment}
 \end{pspicture}
 \end{center}

gives the picture

Notice that the line width does not scale.

16 Plotting With pshacks

pshacks has some built in hooks which, when used with the program TEXGraph, allow for the construction of planar plots. The TEXGraph program should be included in the pshacks setup. It has its own documentation so refer to this if you think you would like to explore the option of using pshacks to make plots. Let me just say here that what TEXGraph will do is create a TEX file which will draw the lines for your plot. The axes and labels may then be filled in by the user with normal pshacks commands. Commands are also provided so that you can perform certain functions (moving and line drawing) in graph coordinates.

17 Making Encapsulated PostScript Figures with pshacks

PSTricks allows one to build an Encapsulated PostScript figure from TEX commands. This feature is made quite straightforward with pshacks commands. If you wish to save a drawing you make as Encapsulated PostScript, simply put the commands for the figure in a file by themselves (no extra text), and replace the pspicture environment with the psdraw environment. Then apply L^{A}TEX to the file and convert the resulting dvi file to Encapsulated PostScript with the -E option for dvips. Your version of dvips must support this option.

To see how to utilise the Encapsulated PostScript capabilities, and to see what kinds of things you can do with pshacks, there are some sample files included with the documentation for pshacks. You should have files sample1.tex,

sample2.tex, sample3.tex and sample.tex. First apply L^{A}TEX, then dvips (with
the -E option) to the files sample1.tex, sample2.tex, and sample3.tex. Send
the output of dvips to files sample1.eps, sample2.eps, and sample3.eps using

the -o option. Then apply L^{A}TEX to sample.tex to see the sample files and the pictures they produce. Note: You will need graphicx or graphics to include any Encapsulated PostScript files in your TEX output. To specify which you wish package you wish to use, specify one of the options graphics or graphicx. The default is graphicx.

18 Handling TEX Overflows

You may find that if you have many figures, or figures with a lot of pshacks commands, you may get a TEX overflow message. Really the only way to get around this is to force pshacks to write its commands to an Encapsulated PostScript file rather than to a \special hook. You may do this with an entire figure or only parts of it. To create an Encapsulated PostScript file from pshacks commands, put the commands in a file, filename.tex, and put the command

    \epsmake{filename}

in the file. Here filename should be the name of the file without the .tex suffix. This will create nothing in your file. However, the resulting Encapsulated PostScript file, filename.eps, can be placed in a pspicture or psdraw environment with the command

    \epsput{filename}

Often one may wish to create the Encapsulated PostScript and immediately include it right where it is supposed to be. In this case use the command \epsmp. As an example, the commands

    \begin{pspicture}(x_{0},y_{0})(x_{1},y_{1})

           .

first pshacks commands

           .
    \epsmp{filename}
           .

second pshacks commands

           .
    \end{pspicture}

will produce the same results as

    \begin{pspicture}(x_{0},y_{0})(x_{1},y_{1})

           .

first pshacks commands

           .
    \input{filename}
           .

second pshacks commands

           .
    \end{pspicture}

However, if the pshacks commands in filename.tex would have caused TEX to overflow, this would be averted. This feature is especially useful with TEXGraph where one may wish to plot large data files.

19 Computations

For convenience, pshacks has some macros for performing algebraic operations.

\realmult{x_{1}}{x_{2}}{y}: The product of real numbers x_{1} and x_{2} is returned to y.

\intdiv{i_{1}}{i_{2}}{x}: The quotient of integers i_{1} and i_{2} is returned to the real number x.

\realadd{x_{1}}{x_{2}}{y}: The sum of real numbers x_{1} and x_{2} is returned to y.

\realdiv{x_{1}}{x_{2}}{y}: The quotient of real numbers x_{1} and x_{2} is returned to y.

20 Alphabetic Review of Command Descriptions

For quick reference, here is a list of the commands in alphabetical order.

\arc*[arr]{r}(θ_{1},θ_{2}): Draws a counterclockwise arc of radius r between the angles θ_{1} and θ_{2} with arrow type arr.

\cengrav{r}: Make a centre of gravity symbol of radius r.

\cir*[fill]{r}: Draws a circle centred at the current location of radius r with fill density fill.

\closedspline*[fill](x_{0},y_{0})...(x_{n},y_{n}): Draws a closed spline though the points (x_{0}, y_{0})… (x_{n}, y_{n}) with fill level fill.

\cvec*[arr](x_{0},y_{0})(x_{1},y_{1})(x_{2},y_{2})(x_{3},y_{3}): Draws a Bézier curve from (x_{0}, y_{0}) to (x_{3}, y_{3}) with control points (x_{1}, y_{1}) and (x_{2}, y_{2}) and arrow style arr.

\dashedlines: Sets the line style to dashed.

\dblarclbl*{r}(θ_{1},θ_{2}){text}{ϕ}: Makes a counterclockwise arc of radius r between the angles θ_{1} and θ_{2}. There is an arrow at each end and the label text is in the middle of the arc in a gap of angular width ϕ. The angles θ_{1} and θ_{2} must be numbers with absolute value less than or equal to 360.

\drawhbox*[fill](lenx,leny)[arg]: Draws a box whose orientation is 0. The box is positioned according to arg. See Section 4 for the possibilities.

\drawhcbox*[fill](lenx,leny){r}[arg]: Draws a box with corners radiused to r whose orientation is 0. The box is positioned according to arg. See Section 4 for the possibilities.

\drawrbox*{θ}[fill](lenx,leny)[arg]: Draws a box of dimensions lenx × leny and orientation θ. The box is filled to intensity fill. The box is positioned according to arg. See Section 4 for the possibilities.

\drawrcbox*{θ}[fill](lenx,leny){r}[arg]: Draws a box with corners radiused to r of dimensions lenx × leny and orientation θ. The box is filled to intensity fill. The box is positioned according to arg. See Section 4 for the possibilities.

\ellip*[fill]{radx}{rady}{θ}: Draws an ellipse centred at the current location with radius in the x-direction of radx, radius in the y-direction of rady. The x-axis of the ellipse makes an angle of θ degrees with the reference x-axis, and the ellipse is filled to density fill.

\elliparc*{radx}{rady}(θ_{1},θ_{2}){ψ}: Draws the arc of an ellipse centred at the current location with x-radius radx and y-radius rady with the x-axis of the ellipse making an angle ψ with the horizontal. The angles θ_{1} and θ_{2} have something to to with the extent of the arc and work something like the arguments for \arc.

\epsmake{filename}: Takes the file filename with pshacks commands and makes the Encapsulated PostScript file filename.eps.

\epsmp{filename}: Combines \epsmake and \epsput.

\epsmake{filename}: Takes the Encapsulated PostScript file, filename.eps, and includes it at the current spot in the pspicture or psdraw environment.

\espline*[arr](x_{0},y_{0})...(x_{n},y_{n}): Draws a splined curve through the points (x_{1}, y_{1})… (x_{n−1}, y_{n−1}) with arrow style arr. The points (x_{0}, y_{0}) and (x_{n}, y_{n}) go into the computation of the ends of the spline. fillcolor{color}: Inside this environment, all optional fills will be made with the

colour color. The value of the optional fill argument within this environment is irrelevant except in that it must be present.

fillstyle{style}: Inside this environment, all optional fills are made with the fill

style style. \htext[arg]{text}: This places horizontal text, text, at the current location with

positioning specified by arg. For possible values of arg, see Section 4. \intdiv{i_{1}}{i_{2}}{x}: The quotient of integers i_{1} and i_{2} is returned to the real

number x. \move(x,y): This will move you to the absolute coordinate (x, y). \oldvec: This command was \vec in L^{A}TEX, but \vec is redefined by pshacks, so

it has this new name. \openspline*[arr](x_{0},y_{0} )...(x_{n},y_{n}): Draws a splined curve through the

points (x_{0}, y_{0})… (x_{n}, y_{n}) with arrow style arr. \polygon*[fill](x_{0},y_{0})...(x_{n},y_{n}): Draws a polygon with vertices (x_{0}, y_{0})… (x_{n}, y_{n})

filled to level fill. psdraw: A version of pspicture which is used for making Encapsulated PostScript

figures. pspicture: The basic PSTricks drawing environment within which the pshacks

macros were designed to work. \pswedge*[fill]{rad}(θ_{1},θ_{2}): Draws a wedge at the current location filled to fill,

of radius rad, and between angles θ_{1} and θ_{2}. \rarrow{θ}: Makes an arrow with its head at the current location pointing in the

direction θ. \rdblaveclbl*{r}{θ}{text}{width}: Makes a double arrowed line of length r

from the current location in the direction θ. The label text is place in the middle of the line in a gap of width width.

\realadd{x_{1}}{x_{2}}{y}: The sum of real numbers x_{1} and x_{2} is returned to y. \realdiv{x_{1}}{x_{2}}{y}: The quotient of real numbers x_{1} and x_{2} is returned to y. \realmult{x_{1}}{x_{2}}{y}: The product of real numbers x_{1} and x_{2} is returned to y. \relmove(dx,dy): This will move you from your current location a relative dis-

placement (dx, dy). \relvec*[arr](dx,dy): Draws a line with relative coordinates (dx, dy) with ar-

row style arr.

\rmove{r}{θ}: This will move a distance r along a line with angle θ. \rtext{θ}[arg]{text}: This places text, text, at the current location with orien-

tation θ with positioning specified by arg. For possible values of arg, see Section 4.

\rvec*[arr]{r}{θ}: Draws a line of length r at an angle θ with arrow style arr. \savecurrpos(x,y): Saves the current position which may later be referenced by

     (\usecoor{x},\usecoor{y}).

\scalelines{factor}: Scales the default line width by factor. The default line

width is 0.8pt. segment: An environment which has its own coordinate system and allows for

internal scaling. \setrelscale{factor}: Sets the scale to the current scale multiplied by factor. \setrelsegscale{factor}: Sets the segment scale to the current segment scale

multiplied by factor. \setscale{scale}: Scales the overall figure by scale. If placed before \begin{pspicture},

the units in the argument will also be scaled. \setsegscale{scale}: Scales the segment to scale. \usecoor{name}: Returns the numerical value of the coordinate name savec with

     \savecurrpos.

\vec*[arr](x,y): Draws a line to the point (x, y) with arrow style arr. \vtext[arg]{text}: This places vertical text, text, at the current location with

positioning specified by arg. For possible values of arg, see Section 4.

21 Implementation

1 ⟨∗package⟩

Load the necessary packages, and immediately make modifications to a few pstricks macros so as to be compatible with pshacks.

 2 \RequirePackage{pstricks,pst-eps,trig}

3

A modified pspicture environment to move to (0,0) at the inception.

 4 \def\pst@@@picture[#1](#2,#3)(#4,#5){%
 5 \pssetxlength\pst@dima{#2}\pssetylength\pst@dimb{#3}%
 6 \pssetxlength\pst@dimc{#4}\pssetylength\pst@dimd{#5}%
 7 \def\pst@tempa{#1}%
 8 \setbox\pst@hbox=\hbox\bgroup
 9 \begingroup\KillGlue

10 \@ifundefined{@latexerr}{}{\let\unitlength\psunit}%
11 \edef\pic@coor{(#2,#3)(#2,#3)(#4,#5)}\move(0,0)\ignorespaces}

12

Hack for resetting options for closed objects.

13 \def\end@ClosedObj{%
14 \ifpsshadow \pst@closedshadow \fi
15 \ifdim\psk@border\p@>\z@ \pst@addborder \fi
16 \psk@fillstyle
17 \pst@stroke
18 \ifpsdoubleline \pst@doublestroke \fi
19 \ifshowpoints
20 % Modification Denis GIROU (CNRS/IDRIS - France) - &lt;Denis.Girou@idris.fr&gt; -  4 Mar. 1995
21 %\addto@pscode{Points aload length 2 div cvi /N ED \psdots@iii}%
22 \pst@OpenShowPoints
23 % End modification D.G.
24 \fi
25 \use@pscode
26 \endgroup\@optreset
27 \ignorespaces}

28

Hack to make fills work in pshacks.

29 \def\psset@fillstyle#1{%
30 \edef\pst@tempg{#1}\def\pst@temph{none}%
31 \ifx\pst@tempg\pst@temph
32 \let\psk@fillstyle\relax
33 \else
34 \@ifundefined{psfs@#1}%
35 {\@pstrickserr{Undefined fill style: `#1'}\@eha}%
36 {\edef\psk@fillstyle{\expandafter\noexpand\csname psfs@#1\endcsname}%
37 \edef\psfillstyle{#1}}%
38 \fi}

39

Options.

40 \newif\if@globalcolors\@globalcolorstrue
41 \DeclareOption{nocolors}{\@globalcolorsfalse}
42 \DeclareOption{graphics}{\def\@ADL@@graphics{\@ne}}
43 \DeclareOption{graphicx}{\def\@ADL@@graphics{\z@}}
44 \ExecuteOptions{graphicx}
45 \ProcessOptions
46 \ifnum\@ADL@@graphics=\@ne
47 \RequirePackage{graphics}
48 \else
49 \RequirePackage{graphicx}
50 \fi

51

Default settings and initialisation.

52 \psset{fillstyle=none,dash=2pt 2pt,cornersize=absolute}
53 \newgray{faintgray}{0.95}

54 \edef\@currcolor{white}
55 \def\@forwardarrow{->}
56 \def\@xcurr{0}
57 \def\@ycurr{0}

58

The “Send to PostScript” environment.

59 \newcommand\psdraw{\@ifstar{\@psdrawstar}{\@psdrawnostar}}
60 \def\@psdrawstar(#1,#2)(#3,#4){\TeXtoEPS\pspicture*(#1,#2)(#3,#4)\move(0,0)}
61 \def\@psdrawnostar(#1,#2)(#3,#4){\TeXtoEPS\pspicture(#1,#2)(#3,#4)\move(0,0)}
62 \def\endpsdraw{\endpspicture\endTeXtoEPS}

63

Segments.

64 \@ifundefined{segment}{%
65 \newenvironment{segment}{\savecurrpos(@xsegor,@ysegor)
66 \begingroup\let\move\@segmove\let\@coordupdate\@segcoordupdate
67 \move(0,0)}{\endgroup}}
68 {\PackageWarning{pshacks}%
69 {Redefining \string\segment\space to \string\oldsegment}
70 \renewenvironment{segment}{\savecurrpos(@xsegor,@ysegor)
71 \begingroup\let\move\@segmove\let\@coordupdate\@segcoordupdate
72 \move(0,0)}{\endgroup}}

73

Colours and fill styles for optional filling.

74 \newif\if@colorset\@colorsetfalse
75 \newenvironment{fillcolor}[1]{\if@globalcolors\@colorsettrue
76 \psset{fillcolor=#1}\fi\edef\@currcolor{#1}}
77 {\if@globalcolors\@colorsetfalse\fi\edef\@currcolor{white}}
78 \newcommand\@fillcolor[1]{\if@colorset\psset@fillcolor{\@currcolor}
79 \else\@fillcomp{#1}\@grayscale\newgray{@tempcolor}{\@grayscale}
80 \psset@fillcolor{@tempcolor}\edef\@currcolor{@tempcolor}\fi}
81 \newif\if@fillstyleset\@fillstylesetfalse
82 \newenvironment{fillstyle}[1]{\@fillstylesettrue\psset{fillstyle=#1}
83 \edef\@currfillstyle{#1}}{\@fillstylesetfalse\edef\@currfillstyle{none}}
84 \newcommand\@fillstyle{\if@fillstyleset\psset@fillstyle{\@currfillstyle}\else
85 \psset@fillstyle{solid}\fi}
86 \newcommand\@optreset{\psset@fillcolor{white}\psset@fillstyle{none}}

87

Scaling.

88 \def\@scale{1}
89 \def\@segscale{1}
90 \newcommand\setscale[1]{\realmult{1}{#1}\@scale \psset{unit=\@scale cm}}
91 \newcommand\setrelscale[1]{\realmult{\@scale}{#1}\@scale
92 \psset{unit=\@scale cm}}
93 \newcommand\setsegscale[1]{\move(\@@@xsegor@@,\@@@ysegor@@)
94 \realmult{1}{#1}\@segscale \psset{unit=\@segscale cm}
95 \realdiv{\@@@xsegor@@}{\@segscale}\@@@xsegor@@
96 \realdiv{\@@@ysegor@@}{\@segscale}\@@@ysegor@@}
97 \newcommand\setrelsegscale[1]{\move(\@@@xsegor@@,\@@@ysegor@@)

 98 \realmult{\@segscale}{#1}\@segscale \psset{unit=\@segscale cm}
 99 \realdiv{\@@@xsegor@@}{\@segscale}\@@@xsegor@@
100 \realdiv{\@@@ysegor@@}{\@segscale}\@@@ysegor@@}

101

Coordinate handling.

102 \def\@coordupdate(#1,#2){\@realadd{\@xcurr}{#1}\@xcurr
103 \@realadd{\@ycurr}{#2}\@ycurr}
104 \def\@segcoordupdate(#1,#2){\realadd{\@xcurr}{#1}\@xcurr
105 \realadd{\@ycurr}{#2}\@ycurr}
106 \newcommand\@polarcoordupdate[2]{\@polartocart{#1}{#2}\@xincr\@yincr
107 \@coordupdate(\@xincr,\@yincr)}
108 \newcommand\@polartocart[4]{\CalculateCos{#2}\CalculateSin{#2}
109 \realmult{#1}{\UseCos{#2}}{#3}\realmult{#1}{\UseSin{#2}}{#4}}

110

Saving coordinates.

111 \def\savecurrpos(#1,#2){\expandafter\let\csname @@#1@@\endcsname\@xcurr
112 \expandafter\let\csname @@#2@@\endcsname\@ycurr}
113 \newcommand\usecoor[1]{\csname @@#1@@\endcsname}
114 \newcommand\cpair[1]{\usecoor{x#1},\usecoor{y#1}}

115

Moving.

116 \def\move(#1,#2){\xdef\@xcurr{#1}\xdef\@ycurr{#2}}
117 \def\relmove(#1,#2){\@coordupdate(#1,#2)}
118 \newcommand\rmove[2]{\@polarcoordupdate{#1}{#2}}
119 \def\@segmove(#1,#2){\realadd{\@@@xsegor@@}{#1}\@xcurr
120 \realadd{\@@@ysegor@@}{#2}\@ycurr}

121

Lines. Note that \vec loses its current definition!

122 \newcommand\scalelines[1]{\realmult{#1}{0.8}\@temp\psset{linewidth=\@temp pt}}
123 \newcommand\dashedlines{\psset{linestyle=dashed}}
124 \PackageWarning{pshacks}{Redefining \string\vec\space to \string\oldvec}
125 \let\oldvec\vec
126 \renewcommand\vec{\@ifstar{\@vecstar}{\@vecnostar}}
127 \newcommand\@vecstar{\@ifnextchar[{\@dashvec}{\@dashvec[-]}}
128 \newcommand\@vecnostar{\@ifnextchar[{\@vec}{\@vec[-]}}
129 \def\@dashvec[#1](#2,#3){\savecurrpos(@xtemp,@ytemp)\move(#2,#3)
130 \psline[linestyle=dashed]{#1}(\usecoor{@xtemp},\usecoor{@ytemp})%
131 (\@xcurr,\@ycurr)}
132 \def\@vec[#1](#2,#3){\savecurrpos(@xtemp,@ytemp)\move(#2,#3)
133 \psline{#1}(\usecoor{@xtemp},\usecoor{@ytemp})(\@xcurr,\@ycurr)}
134 \newcommand\relvec{\@ifstar{\@relvecstar}{\@relvecnostar}}
135 \newcommand\@relvecstar{\@ifnextchar[{\@reldashvec}{\@reldashvec[-]}}
136 \newcommand\@relvecnostar{\@ifnextchar[{\@relvec}{\@relvec[-]}}
137 \def\@reldashvec[#1](#2,#3){\savecurrpos(@xtemp,@ytemp)\@coordupdate(#2,#3)
138 \psline[linestyle=dashed]{#1}(\usecoor{@xtemp},\usecoor{@ytemp})%
139 (\@xcurr,\@ycurr)}
140 \def\@relvec[#1](#2,#3){\savecurrpos(@xtemp,@ytemp)\@coordupdate(#2,#3)
141 \psline{#1}(\usecoor{@xtemp},\usecoor{@ytemp})(\@xcurr,\@ycurr)}

142 \newcommand\rvec{\@ifstar{\@rvecstar}{\@rvecnostar}}
143 \newcommand\@rvecstar{\@ifnextchar[{\@rdashvec}{\@rdashvec[-]}}
144 \newcommand\@rvecnostar{\@ifnextchar[{\@rvec}{\@rvec[-]}}
145 \def\@rdashvec[#1]#2#3{\savecurrpos(@xtemp,@ytemp)\@polarcoordupdate{#2}{#3}
146 \psline[linestyle=dashed]{#1}(\usecoor{@xtemp},\usecoor{@ytemp})%
147 (\@xcurr,\@ycurr)}
148 \def\@rvec[#1]#2#3{\savecurrpos(@xtemp,@ytemp)\@polarcoordupdate{#2}{#3}
149 \psline{#1}(\usecoor{@xtemp},\usecoor{@ytemp})(\@xcurr,\@ycurr)}

150

Arrow with a label in the middle.

151 \newcommand\rdblaveclbl{\@ifstar{\@rdblaveclblstar}{\@rdblaveclblnostar}}
152 \newcommand\@rdblaveclblstar[4]{\savecurrpos(@xtemp,@ytemp)
153 \realmult{#1}{0.5}\@halflen\realmult{#4}{0.5}\@halfgap
154 \realadd{\@halflen}{-\@halfgap}\@linelen
155 {\psset{linestyle=dashed}\rvec[<-]{\@linelen}{#2}\rmove{\@halfgap}{#2}
156 \rput(\@xcurr,\@ycurr){#3}\rmove{\@halfgap}{#2}\rvec[->]{\@linelen}{#2}}
157 \move(\usecoor{@xtemp},\usecoor{@ytemp})}
158 \newcommand\@rdblaveclblnostar[4]{\savecurrpos(@xtemp,@ytemp)
159 \realmult{#1}{0.5}\@halflen
160 \realmult{#4}{0.5}\@halfgap\realadd{\@halflen}{-\@halfgap}\@linelen
161 \rvec[<-]{\@linelen}{#2}\rmove{\@halfgap}{#2}\rput(\@xcurr,\@ycurr){#3}
162 \rmove{\@halfgap}{#2}\rvec[->]{\@linelen}{#2}
163 \move(\usecoor{@xtemp},\usecoor{@ytemp})}

164

Circles.

165 \@ifundefined{cir}{%
166 \newcommand\cir{\@ifstar{\@cirstar}{\@cirnostar}}}
167 {\PackageWarning{pshacks}{Redefining \string\cir to \string\oldcir}
168 \let\oldcir\cir
169 \renewcommand\cir{\@ifstar{\@cirstar}{\@cirnostar}}}
170 \newcommand\@cirstar{\@ifnextchar[{\@dashfcir}{\@dashlcir}}
171 \newcommand\@cirnostar{\@ifnextchar[{\@fcir}{\@lcir}}
172 \newcommand\@dashlcir[1]{\pscircle[linestyle=dashed](\@xcurr,\@ycurr){#1}}
173 \def\@dashfcir[#1]#2{\@fillcolor{#1}\@fillstyle%
174 \pscircle[fillcolor=\@currcolor,fillstyle=solid,linestyle=dashed]%
175 (\@xcurr,\@ycurr){#2}\@optreset}
176 \newcommand\@lcir[1]{\pscircle(\@xcurr,\@ycurr){#1}}
177 \def\@fcir[#1]#2{\@fillcolor{#1}\@fillstyle\pscircle[fillcolor=\@currcolor,%
178 fillstyle=\psfillstyle](\@xcurr,\@ycurr){#2}\@optreset}

179

Just arrows.

180 \newcommand\rarrow[1]{\rmove{-0.01}{#1}\rvec[->]{0.01}{#1}}

181

Centre of gravity symbol.

182 \newcommand\cengrav[1]{\cir[0]{#1}\oldpswedge[fillcolor=black,fillstyle=solid]%
183 (\@xcurr,\@ycurr){#1}{0}{90}\oldpswedge[fillcolor=black,fillstyle=solid]%
184 (\@xcurr,\@ycurr){#1}{180}{270}}

185

Arcs.

186 \newcommand\arc{\@ifstar{\@arcstar}{\@arcnostar}}
187 \newcommand\@arcstar{\@ifnextchar[{\@dasharc}{\@dasharc[-]}}
188 \newcommand\@arcnostar{\@ifnextchar[{\@arc}{\@arc[-]}}
189 \def\@dasharc[#1]#2(#3,#4){\psarc[linestyle=dashed]{#1}(\@xcurr,\@ycurr)%
190 {#2}{#3}{#4}}
191 \def\@arc[#1]#2(#3,#4){\psarc{#1}(\@xcurr,\@ycurr){#2}{#3}{#4}}
192 \newcommand\dblarclbl{\@ifstar{\@dblarclblstar}{\@dblarclblnostar}}
193 \def\@dblarclblstar{\@ifnextchar[{\@dblarclblstararr}{\@dblarclblstarnoarr}}
194 \def\@dblarclblstararr[#1]#2(#3,#4)#5#6
195 {\def\@arrowarg{#1}\@angle{#3}\@angone\@angle{#4}\@angtwo
196 \realadd{\@angtwo}{-\@angone}\@testarc\realcomp{\@testarc}{0}\@testres
197 \ifx\@testres\@gtest\realadd{\@testarc}{0}\@larc\else
198 \ifx\@testres\@ltest\realadd{\@testarc}{360}\@larc\else\errmessage{Angles for
199 dblarclbl are equal}\fi\fi
200 \realmult{#6}{0.5}\@halfgap\realmult{\@larc}{0.5}\@halfarc
201 \realadd{\@halfarc}{-\@halfgap}\@arcdraw\realadd{\@angone}{\@arcdraw}\@dumang
202 \ifx\@arrowarg\@forwardarrow
203  \psarc[linestyle=dashed]{-}(\@xcurr,\@ycurr){#2}{\@angone}{\@dumang}
204 \else
205  \psarc[linestyle=dashed]{<-}(\@xcurr,\@ycurr){#2}{\@angone}{\@dumang}
206 \fi
207 \realadd{\@angtwo}{-\@arcdraw}\@dumang
208 \ifx\@arrowarg\@forwardarrow
209  \psarc[linestyle=dashed]{->}(\@xcurr,\@ycurr){#2}{\@dumang}{\@angtwo}
210 \else
211  \psarc[linestyle=dashed]{-}(\@xcurr,\@ycurr){#2}{\@dumang}{\@angtwo}
212 \fi
213 \realadd{\@dumang}{-\@halfgap}\@lblang
214 \@polartocart{#2}{\@lblang}\@xtemp\@ytemp
215 \realadd{\@xtemp}{\@xcurr}\@xtemp\realadd{\@ytemp}{\@ycurr}\@ytemp
216 \rput(\@xtemp,\@ytemp){#5}}
217 \def\@dblarclblstarnoarr#1(#2,#3)#4#5{\@angle{#2}\@angone\@angle{#3}\@angtwo
218 \realadd{\@angtwo}{-\@angone}\@testarc\realcomp{\@testarc}{0}\@testres
219 \ifx\@testres\@gtest\realadd{\@testarc}{0}\@larc\else
220 \ifx\@testres\@ltest\realadd{\@testarc}{360}\@larc\else\errmessage{Angles for
221 dblarclbl are equal}\fi\fi
222 \realmult{#5}{0.5}\@halfgap\realmult{\@larc}{0.5}\@halfarc
223 \realadd{\@halfarc}{-\@halfgap}\@arcdraw\realadd{\@angone}{\@arcdraw}\@dumang
224 \psarc[linestyle=dashed]{<-}(\@xcurr,\@ycurr){#1}{\@angone}{\@dumang}
225 \realadd{\@angtwo}{-\@arcdraw}\@dumang
226 \psarc[linestyle=dashed]{->}(\@xcurr,\@ycurr){#1}{\@dumang}{\@angtwo}
227 \realadd{\@dumang}{-\@halfgap}\@lblang
228 \@polartocart{#1}{\@lblang}\@xtemp\@ytemp
229 \realadd{\@xtemp}{\@xcurr}\@xtemp\realadd{\@ytemp}{\@ycurr}\@ytemp
230 \rput(\@xtemp,\@ytemp){#4}}
231 \def\@dblarclblnostar{\@ifnextchar[{\@dblarclblnostarnoarr}
232 {\@dblarclblnostararr}}
233 \def\@dblarclblnostarnoarr[#1]#2(#3,#4)#5#6
234 {\def\@arrowarg{#1}\@angle{#3}\@angone\@angle{#4}\@angtwo

235 \realadd{\@angtwo}{-\@angone}\@testarc\realcomp{\@testarc}{0}\@testres
236 \ifx\@testres\@gtest\realadd{\@testarc}{0}\@larc\else
237 \ifx\@testres\@ltest\realadd{\@testarc}{360}\@larc\else\errmessage{Angles for
238 dblarclbl are equal}\fi\fi
239 \realmult{#6}{0.5}\@halfgap\realmult{\@larc}{0.5}\@halfarc
240 \realadd{\@halfarc}{-\@halfgap}\@arcdraw\realadd{\@angone}{\@arcdraw}\@dumang
241 \ifx\@arrowarg\@forwardarrow
242  \psarc{-}(\@xcurr,\@ycurr){#2}{\@angone}{\@dumang}
243 \else
244  \psarc{<-}(\@xcurr,\@ycurr){#2}{\@angone}{\@dumang}
245 \fi
246 \realadd{\@angtwo}{-\@arcdraw}\@dumang
247 \ifx\@arrowarg\@forwardarrow
248  \psarc{->}(\@xcurr,\@ycurr){#2}{\@dumang}{\@angtwo}
249 \else
250  \psarc{-}(\@xcurr,\@ycurr){#2}{\@dumang}{\@angtwo}
251 \fi
252 \realadd{\@dumang}{-\@halfgap}\@lblang
253 \@polartocart{#2}{\@lblang}\@xtemp\@ytemp
254 \realadd{\@xtemp}{\@xcurr}\@xtemp\realadd{\@ytemp}{\@ycurr}\@ytemp
255 \rput(\@xtemp,\@ytemp){#5}}
256 \def\@dblarclblnostararr#1(#2,#3)#4#5{\@angle{#2}\@angone\@angle{#3}\@angtwo
257 \realadd{\@angtwo}{-\@angone}\@testarc\realcomp{\@testarc}{0}\@testres
258 \ifx\@testres\@gtest\realadd{\@testarc}{0}\@larc\else
259 \ifx\@testres\@ltest\realadd{\@testarc}{360}\@larc\else\errmessage{Angles for
260 dblarclbl are equal}\fi\fi
261 \realmult{#5}{0.5}\@halfgap\realmult{\@larc}{0.5}\@halfarc
262 \realadd{\@halfarc}{-\@halfgap}\@arcdraw\realadd{\@angone}{\@arcdraw}\@dumang
263 \psarc{<-}(\@xcurr,\@ycurr){#1}{\@angone}{\@dumang}
264 \realadd{\@angtwo}{-\@arcdraw}\@dumang
265 \psarc{->}(\@xcurr,\@ycurr){#1}{\@dumang}{\@angtwo}
266 \realadd{\@dumang}{-\@halfgap}\@lblang
267 \@polartocart{#1}{\@lblang}\@xtemp\@ytemp
268 \realadd{\@xtemp}{\@xcurr}\@xtemp\realadd{\@ytemp}{\@ycurr}\@ytemp
269 \rput(\@xtemp,\@ytemp){#4}}

270

Wedges.

271 \PackageWarning{pshacks}{Redefining \string\pswedge\space to
272 \string\oldpswedge}
273 \let\oldpswedge\pswedge
274 \renewcommand\pswedge{\@ifstar{\@wedgestar}{\@wedgenostar}}
275 \newcommand\@wedgestar{\@ifnextchar[{\@dashfwedge}{\@dashlwedge}}
276 \newcommand\@wedgenostar{\@ifnextchar[{\@fwedge}{\@lwedge}}
277 \def\@dashlwedge#1(#2,#3){\oldpswedge[linestyle=dashed]{#1}{#2}{#3}}
278 \def\@dashfwedge[#1]#2(#3,#4){\@fillcolor{#1}\@fillstyle%
279 \oldpswedge[fillcolor=\@currcolor,fillstyle=\psfillstyle,linestyle=dashed]%
280 (\@xcurr,\@ycurr){#2}{#3}{#4}\@optreset}
281 \def\@lwedge#1(#2,#3){\oldpswedge{#1}{#2}{#3}}
282 \def\@fwedge[#1]#2(#3,#4){\@fillcolor{#1}\@fillstyle%

283 \oldpswedge[fillcolor=\@currcolor,fillstyle=\psfillstyle](\@xcurr,\@ycurr)%
284 {#2}{#3}{#4}\@optreset}

285

Ellipses.

286 \newcommand\ellip{\@ifstar{\@ellipstar}{\@ellipnostar}}
287 \newcommand\@ellipstar{\@ifnextchar[{\@dashfellip}{\@dashlellip}}
288 \newcommand\@ellipnostar{\@ifnextchar[{\@fellip}{\@lellip}}
289 \def\@dashfellip[#1]#2#3#4{\@fillcolor{#1}\@fillstyle%
290 \rput{#4}(\@xcurr,\@ycurr){\psellipse[fillcolor=\@currcolor,%
291 fillstyle=\psfillstyle,linestyle=dashed](0,0)(#2,#3)}\@optreset}
292 \newcommand\@dashlellip[3]{\rput{#3}(\@xcurr,\@ycurr)%
293 {\psellipse[linestyle=dashed](0,0)(#1,#2)}}
294 \def\@fellip[#1]#2#3#4{\@fillcolor{#1}\@fillstyle\rput{#4}(\@xcurr,\@ycurr){%
295 \psellipse[fillcolor=\@currcolor,fillstyle=\psfillstyle](0,0)(#2,#3)}%
296 \@optreset}
297 \newcommand\@lellip[3]{\rput{#3}(\@xcurr,\@ycurr){\psellipse(0,0)(#1,#2)}}

298

Elliptical arcs. Make some hacks here to the pstricks macros.

299 \newcommand\elliparc{\@ifstar{\@elliparcstar}{\@elliparcnostar}}
300 \def\@elliparcstar#1#2(#3,#4)#5{\rput{#5}(\@xcurr,\@ycurr)%
301 {\psellipsearc[linestyle=dashed](0,0)(#1,#2){#3}{#4}}}
302 \def\@elliparcnostar#1#2(#3,#4)#5{\rput{#5}(\@xcurr,\@ycurr)%
303 {\psellipsearc(0,0)(#1,#2){#3}{#4}}}
304 \newcommand\psellipsearc{\def\pst@par{}\pst@object{psellipsearc}}
305 \def\psellipsearc@i(#1){\@ifnextchar(%
306 {\psellipsearc@ii(#1)}{\psellipsearc@ii(0,0)(#1)}}
307 \def\psellipsearc@ii(#1)(#2)#3#4{%
308 \begin@ClosedObj
309 \pst@getcoor{#1}\pst@tempa
310 \pst@@getcoor{#2}%
311 \addto@pscode{%
312 #3 #4
313 \pst@coor
314 \ifdim\psk@dimen\p@=\z@\else
315 \psk@dimen CLW mul dup 3 1 roll
316 sub 3 1 roll sub exch
317 \fi
318 \pst@tempa
319 \tx@Ellipse1}
320 \def\pst@linetype{2}%
321 \end@ClosedObj}

322

Boxes.

323 \newcommand\drawrbox{\@ifstar{\@drawrboxstar}{\@drawrboxnostar}}
324 \newcommand\@drawrboxstar[1]{\@ifnextchar[{\@dashfillbox{#1}}
325 {\@dashnofillbox{#1}}}
326 \newcommand\@drawrboxnostar[1]{\@ifnextchar[{\@fillbox{#1}}{\@nofillbox{#1}}}
327 \def\@dashfillbox#1[#2](#3,#4){\@ifnextchar[{\@dashfillboxref{#1}[#2](#3,#4)}

328 {\@dashfillboxref{#1}[#2](#3,#4)[cc]}}
329 \def\@fillbox#1[#2](#3,#4){\@ifnextchar[{\@fillboxref{#1}[#2](#3,#4)}
330 {\@fillboxref{#1}[#2](#3,#4)[cc]}}
331 \def\@dashfillboxref#1[#2](#3,#4)[#5]{\@fillcolor{#2}\@fillstyle
332 \@boxstart{#5}{#3}{#4}\@xoffstart\@yoffstart\@xoffend\@yoffend
333 \rput{#1}(\@xcurr,\@ycurr){\psframe[fillcolor=\@currcolor,%
334 fillstyle=\psfillstyle,linestyle=dashed]%
335 (\@xoffstart,\@yoffstart)(\@xoffend,\@yoffend)}\@optreset}
336 \def\@fillboxref#1[#2](#3,#4)[#5]{\@fillcolor{#2}\@fillstyle
337 \@boxstart{#5}{#3}{#4}\@xoffstart\@yoffstart\@xoffend\@yoffend
338 \rput{#1}(\@xcurr,\@ycurr){\psframe[fillcolor=\@currcolor,%
339 fillstyle=\psfillstyle](\@xoffstart,\@yoffstart)(\@xoffend,\@yoffend)}%
340 \@optreset}
341 \def\@dashnofillbox#1(#2,#3){\@ifnextchar[{\@dashnofillboxref{#1}(#2,#3)}
342 {\@dashnofillboxref{#1}(#2,#3)[cc]}}
343 \def\@nofillbox#1(#2,#3){\@ifnextchar[{\@nofillboxref{#1}(#2,#3)}
344 {\@nofillboxref{#1}(#2,#3)[cc]}}
345 \def\@dashnofillboxref#1(#2,#3)[#4]{
346 \@boxstart{#4}{#2}{#3}\@xoffstart\@yoffstart\@xoffend\@yoffend
347 \rput{#1}(\@xcurr,\@ycurr){\psframe[linestyle=dashed]%
348 (\@xoffstart,\@yoffstart)(\@xoffend,\@yoffend)}}
349 \def\@nofillboxref#1(#2,#3)[#4]{
350 \@boxstart{#4}{#2}{#3}\@xoffstart\@yoffstart\@xoffend\@yoffend
351 \rput{#1}(\@xcurr,\@ycurr){\psframe(\@xoffstart,\@yoffstart)%
352 (\@xoffend,\@yoffend)}}
353 \newcommand\drawhbox{\@ifstar{\drawrbox*{0}}{\drawrbox{0}}}
354 \newcommand\drawrcbox{\@ifstar{\@drawrcboxstar}{\@drawrcboxnostar}}
355 \newcommand\@drawrcboxstar[1]{\@ifnextchar[{\@dashfillcbox{#1}}
356 {\@dashnofillcbox{#1}}}
357 \newcommand\@drawrcboxnostar[1]{\@ifnextchar[{\@fillcbox{#1}}
358 {\@nofillcbox{#1}}}
359 \def\@dashfillcbox#1[#2](#3,#4)#5{\@ifnextchar[
360 {\@dashfillcboxref{#1}[#2](#3,#4){#5}}
361 {\@dashfillcboxref{#1}[#2](#3,#4){#5}[cc]}}
362 \def\@fillcbox#1[#2](#3,#4)#5{\@ifnextchar[{\@fillcboxref{#1}[#2](#3,#4){#5}}
363 {\@fillcboxref{#1}[#2](#3,#4){#5}[cc]}}
364 \def\@dashfillcboxref#1[#2](#3,#4)#5[#6]{\@fillcolor{#2}\@fillstyle
365 \@boxstart{#6}{#3}{#4}\@xoffstart\@yoffstart\@xoffend\@yoffend
366 \rput{#1}(\@xcurr,\@ycurr){\psframe[fillcolor=\@currcolor,%
367 fillstyle=\psfillstyle,linearc=#5,linestyle=dashed]%
368 (\@xoffstart,\@yoffstart)(\@xoffend,\@yoffend)}\@optreset}
369 \def\@fillcboxref#1[#2](#3,#4)#5[#6]{\@fillcolor{#2}\@fillstyle
370 \@boxstart{#6}{#3}{#4}\@xoffstart\@yoffstart\@xoffend\@yoffend
371 \rput{#1}(\@xcurr,\@ycurr){\psframe[fillcolor=\@currcolor,%
372 fillstyle=\psfillstyle,linearc=#5]%
373 (\@xoffstart,\@yoffstart)(\@xoffend,\@yoffend)}\@optreset}
374 \def\@dashnofillcbox#1(#2,#3)#4{\@ifnextchar[
375 {\@dashnofillcboxref{#1}(#2,#3){#4}}{\@dashnofillcboxref{#1}(#2,#3){#4}[cc]}}
376 \def\@nofillcbox#1(#2,#3)#4{\@ifnextchar[{\@nofillcboxref{#1}(#2,#3){#4}}
377 {\@nofillcboxref{#1}(#2,#3){#4}[cc]}}

378 \def\@dashnofillcboxref#1(#2,#3)#4[#5]{
379 \@boxstart{#5}{#2}{#3}\@xoffstart\@yoffstart\@xoffend\@yoffend
380 \rput{#1}(\@xcurr,\@ycurr){\psframe[linearc=#4,linestyle=dashed]%
381 (\@xoffstart,\@yoffstart)(\@xoffend,\@yoffend)}}
382 \def\@nofillcboxref#1(#2,#3)#4[#5]{
383 \@boxstart{#5}{#2}{#3}\@xoffstart\@yoffstart\@xoffend\@yoffend
384 \rput{#1}(\@xcurr,\@ycurr){\psframe[linearc=#4](\@xoffstart,\@yoffstart)%
385 (\@xoffend,\@yoffend)}}
386 \newcommand\drawhcbox{\@ifstar{\drawrcbox*{0}}{\drawrcbox{0}}}

387

Figure out where a box starts using placement arguments.

388 \def\@ltest{l}
389 \def\@lbtest{lb}
390 \def\@lttest{lt}
391 \def\@rtest{r}
392 \def\@rbtest{rb}
393 \def\@rttest{rt}
394 \def\@btest{b}
395 \def\@ttest{t}
396 \newcommand\@boxstart[7]{\def\@temp{#1} \realmult{#2}{-0.5}{#4}
397 \realmult{#3}{-0.5}{#5}
398 \ifx \@temp\@ltest
399  \realmult{#2}{0.0}{#4} \realmult{#3}{-0.5}{#5}
400 \fi
401 \ifx \@temp\@lbtest
402  \realmult{#2}{0.0}{#4} \realmult{#3}{0.0}{#5}
403 \fi
404 \ifx \@temp\@lttest
405  \realmult{#2}{0.0}{#4} \realmult{#3}{-1.0}{#5}
406 \fi
407 \ifx \@temp\@rtest
408  \realmult{#2}{-1.0}{#4} \realmult{#3}{-0.5}{#5}
409 \fi
410 \ifx \@temp\@rbtest
411  \realmult{#2}{-1.0}{#4} \realmult{#3}{0.0}{#5}
412 \fi
413 \ifx \@temp\@rttest
414  \realmult{#2}{-1.0}{#4} \realmult{#3}{-1.0}{#5}
415 \fi
416 \ifx \@temp\@btest
417  \realmult{#2}{-0.5}{#4} \realmult{#3}{0.0}{#5}
418 \fi
419 \ifx \@temp\@ttest
420  \realmult{#2}{-0.5}{#4} \realmult{#3}{-1.0}{#5}
421 \fi
422 \realadd{#4}{#2}{#6} \realadd{#5}{#3}{#7}}

423

Polygons.

424 \newcommand\polygon{\@ifstar{\@polygonstar}{\@polygonnostar}}

425 \newcommand\@polygonstar{\@ifnextchar[{\@dashfillpolygon}
426 {\@dashnofillpolygon}}
427 \newcommand\@polygonnostar{\@ifnextchar[{\@fillpolygon}{\pspolygon}}
428 \def\@dashfillpolygon[#1]{\@fillcolor{#1}\@fillstyle%
429 \pspolygon[fillstyle=\psfillstyle,fillcolor=\@currcolor,linestyle=dashed]%

430 }

431 \newcommand\@dashnofillpolygon{\pspolygon[linestyle=dashed]}
432 \def\@fillpolygon[#1]{\@fillcolor{#1}\@fillstyle%
433 \pspolygon[fillstyle=\psfillstyle,fillcolor=\@currcolor]}

434

Bezier curves.

435 \newcommand\cvec{\@ifstar{\@cvecstar}{\@cvecnostar}}
436 \newcommand\@cvecstar{\@ifnextchar[{\@dashcvec}{\@dashcvec[-]}}
437 \newcommand\@cvecnostar{\@ifnextchar[{\@cvec}{\@cvec[-]}}
438 \def\@dashcvec[#1]{\psbezier[linestyle=dashed]{#1}}
439 \def\@cvec[#1]{\psbezier{#1}}

440

Splines.

441 \newcommand\openspline{\@ifstar{\@opensplinestar}{\@opensplinenostar}}
442 \newcommand\@opensplinestar{\@ifnextchar[{\@dashopenspline}
443 {\@dashopenspline[-]}}
444 \newcommand\@opensplinenostar{\@ifnextchar[{\@openspline}{\@openspline[-]}}
445 \def\@dashopenspline[#1]{\pscurve[linestyle=dashed]{#1}}
446 \def\@openspline[#1]{\pscurve{#1}}
447 \newcommand\closedspline{\@ifstar{\@closedsplinestar}{\@closedsplinenostar}}
448 \newcommand\@closedsplinestar{\@ifnextchar[{\@dashfillclosedspline}
449 {\@dashnofillclosedspline}}
450 \newcommand\@closedsplinenostar{\@ifnextchar[{\@fillclosedspline}{\psccurve}}
451 \def\@dashfillclosedspline[#1]{\@fillcolor{#1}\@fillstyle%
452 \psccurve[fillcolor=\@currcolor,fillstyle=\psfillstyle,linestyle=dashed]}
453 \def\@fillclosedspline[#1]{\@fillcolor{#1}\@fillstyle%
454 \psccurve[fillcolor=\@currcolor,fillstyle=\psfillstyle]}
455 \newcommand\@dashnofillclosedspline{\psccurve[linestyle=dashed]}
456 \newcommand\espline{\@ifstar{\@esplinestar}{\@esplinenostar}}
457 \newcommand\@esplinestar{\@ifnextchar[{\@dashespline}{\@dashespline[-]}}
458 \newcommand\@esplinenostar{\@ifnextchar[{\@espline}{\psecurve}}
459 \def\@dashespline[#1]{\psecurve[linestyle=dashed]{#1}}
460 \def\@espline[#1]{\psecurve{#1}}

461

Text.

462 \newcommand\htext{\@ifnextchar[{\@htextref}{\@htextnoref}}
463 \def\@htextref[#1]#2{\rput[#1](\@xcurr,\@ycurr){#2}}
464 \newcommand\@htextnoref[1]{\rput(\@xcurr,\@ycurr){#1}}
465 \newcommand\rtext[1]{\@ifnextchar[{\@rtextref{#1}}{\@rtextnoref{#1}}}
466 \def\@rtextref#1[#2]#3{\rput[#2]{#1}(\@xcurr,\@ycurr){#3}}
467 \newcommand\@rtextnoref[2]{\rput{#1}(\@xcurr,\@ycurr){#2}}
468 \newcommand\vtext{\rtext{90}}

469

Make and include an encapsulated PostScriptfile. This is for large files which overflow TeX.

470 \newcommand\epsmake[1]{\PSTtoEPS{#1.eps}{\input{#1.tex}}}
471 \newcommand\epsput[1]{\rput(0,0){\includegraphics{#1.eps}}}
472 \newcommand\epsmp[1]{\epsmake{#1}\epsput{#1}}

473

Computational tools.

474 \newcount\t@counta
475 \newcount\t@countb
476 \newcount\t@countc
477 \newcount\t@countd
478 \newcount\t@counte
479 \newcommand\realdiv[3]{\dimen0=#1pt \t@counta=\dimen0 \dimen0=#2pt
480 \t@countb=\dimen0 \intdiv \t@counta \t@countb #3}
481 \newcommand\intdiv[3]{\t@counta=#1 \t@countb=#2 \ifnum \t@countb<0
482 \t@counta=-\t@counta \t@countb=-\t@countb \fi \t@countd=1
483 \ifnum \t@counta<0 \t@counta=-\t@counta \t@countd=-1 \fi
484 \t@countc=\t@counta  \divide \t@countc by \t@countb
485 \t@counte=\t@countc  \multiply \t@counte by \t@countb
486 \advance \t@counta by -\t@counte \t@counte=-1
487 \loop \advance \t@counte by 1 \ifnum \t@counte<16
488 \multiply \t@countc by 2 \multiply \t@counta by 2
489 \ifnum \t@counta<\t@countb \else \advance \t@countc by 1
490 \advance \t@counta by -\t@countb \fi \repeat
491 \divide \t@countb by 2 \ifnum \t@counta<\t@countb \advance \t@countc by 1
492 \fi \ifnum \t@countd<0 \t@countc=-\t@countc \fi
493 \dimen0=\t@countc sp \edef #3{\expandafter\c@lean\the\dimen0}}
494 \newcommand\@realadd[3]{\dimen0=#1pt \dimen2=#2pt \advance \dimen0 by \dimen2
495 \xdef #3{\expandafter\c@lean\the\dimen0}}
496 \newcommand\realadd[3]{\dimen0=#1pt \dimen2=#2pt \advance \dimen0 by \dimen2
497 \edef #3{\expandafter\c@lean\the\dimen0}}
498 \newcommand\@realmult[3]{\dimen0=#1pt \dimen2=#2\dimen0
499 \xdef #3{\expandafter\c@lean\the\dimen2}}
500 \newcommand\realmult[3]{\dimen0=#1pt \dimen2=#2\dimen0
501 \edef #3{\expandafter\c@lean\the\dimen2}}
502 \def\@ltest{l}
503 \def\@gtest{g}
504 \def\@etest{e}
505 \newcommand\realcomp[3]{\dimen0=#1pt \dimen2=#2pt \ifdim \dimen0 > \dimen2
506 \def #3{g} \else \ifdim \dimen0 < \dimen2 \def #3{l} \else
507 \def #3{e} \fi \fi}
508 \newcommand\@angle[2]{\dimen0=#1pt \ifdim\dimen0<\z@\realadd{#1}{360}{#2}
509 \else \edef #2{\expandafter\c@lean\the\dimen0}\fi}
510 \newcommand\@fillcomp[2]{\realadd{#1}{-1}\@tempa\realmult{\@tempa}{-1}#2}
511 {\catcode`\p=12 \catcode`\t=12
512 \gdef\c@lean #1pt{#1}}

513

TEXGraph hooks.

514 \def\grmove(#1,#2){\@realmult{#1}{\xscale}\@temp

515 \@realadd{\@temp}{\xoff}\xgrpos \@realmult{#2}{\yscale}\@temp
516 \@realadd{\@temp}{\yoff}\ygrpos \move(\xgrpos,\ygrpos)}
517 \newcommand\grvec{\@ifnextchar[{\@grvec}{\@grvec[-]}}
518 \def\@grvec[#1](#2,#3){\@realmult{#2}{\xscale}\@temp
519 \@realadd{\@temp}{\xoff}\xgrpos \@realmult{#3}{\yscale}\@temp
520 \@realadd{\@temp}{\yoff}\ygrpos \vec[#1](\xgrpos,\ygrpos)}
521 \def\grrelmove(#1,#2){\@realmult{#1}{\xscale}\xgrpos
522 \@realmult{#2}{\yscale}\ygrpos \relmove(\xgrpos,\ygrpos)}
523 \newcommand\grrelvec{\@ifnextchar[{\@grrelvec}{\@grrelvec[-]}}
524 \def\@grrelvec[#1](#2,#3){\@realmult{#2}{\xscale}\xgrpos
525 \@realmult{#3}{\yscale}\ygrpos \relvec[#1](\xgrpos,\ygrpos)}

526

527 ⟨/package⟩