summaryrefslogtreecommitdiff
path: root/usergrps/uktug/baskervi/6_4/pstrix4.tex
blob: f042e802bf630c050a2db1da7a5a83b9a2f3090d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
\author[Sebastian Rahtz]{Sebastian Rahtz\\
Elsevier Science Ltd\\The Boulevard, Langford
Lane\\Kidlington\\
Oxford, UK\\\texttt{s.rahtz@elsevier.co.uk}}\title{An introduction to PSTricks, part 4}
\begin{Article}
This article concludes my look at \PST{}. I hope you have
enjoyed the show! The material has been drawn from a forthcoming book,
entitled \emph{The \LaTeX{} Graphics Companion}, by Michel Goossens,
Sebastian Rahtz and Frank Mittelbach, to be published by Addison
Wesley in 1997. If you have enjoyed \BV{} articles in the last
couple of years on Seminar, colour in \LaTeX, and \PST, you may find
the book of interest.

In this final part, we look briefly at data plotting, and then
conclude with some finished examples of \PST, which are designed
to show the power of the macros in unusual ways.

\section{Data plotting}
\PST\ has a set of high-level tools for common data-plotting
functions; these can read data from external files, in a variety of
formats. We will not tabulate the extra commands or graphical parameters
this time, as they can be easily found in the \PST{} documentation.
The simplest form of data is  a set of comma or white-space delimited
numbers, but values can also be enclosed in braces (\verb|{}|) or
round brackets (\verb|()|). If the data is enclosed in a single
set of \emph{square} brackets (\verb|[]|), and the opening \verb=[= is at the
start of a line, it will be read much faster; however, it will run
\TeX\ out of memory sooner. Data can also be read once, and then
re-used, with the \Lcs{readdata} and \Lcs{savedata} commands. There is
an important distinction between \Lcs{fileplot} or \Lcs{dataplot}
which parse and validate the data in \TeX, and \Lcs{listplot}, which
simply passes the data on to \PS; the latter approach means that there
is no check on \PS\ memory requirements, but has the advantage that
raw \PS\ can be provided to generate or manipulate the data.
Just to complicate matters, use of the \Lcs{PSTtoEPS} command with the
plotting commands can allow for even bigger datasets. An example of
this is given below, in section~\ref{PSTprog}.

It is important to realize that it is up to the user to check the
data extents and scaling; \PST\ does not make the data fit a
predefined plot area, unlike many other packages. Normally, judicious
setting of \PKey{xunit} and \PKey{yunit} will quickly produce nice
results. Axes are generated separately, and there is no provision for
supplying specific labels for axis tick points. It is, on the other
hand, easy to superimpose multiple plots, and use the \PS\ language to
calculate functions, as the following example shows, overlaying
$\sin(x)$, $\sin(x)\cos(x)$ and $\cos(x)$. 

\begin{example*}
\begin{pspicture}(-1,-2.5)(9,2.5)
\psset{xunit=.20mm,yunit=1.75cm}
\psset{plotpoints=50}
\psplot[linestyle=dashed,linecolor=blue]
 {0}{360}{x sin}
\psplot[plotstyle=dots,dotstyle=triangle]
 {0}{360}{x cos}
\psset{plotpoints=200}
\psplot[linecolor=red]{0}{360}
 {x dup sin exch cos mul}
\end{pspicture}
\end{example*}

The next example shows how the \Lcs{psaxes} command can 
be used to create graph frames; in this mode, it obeys the graphical
fill and colour parameters. This picture (showing 
word length ($x$ axis) against occurrences ($y$ axis) in a passage of
Dickens) also shows how the axis labels can be manipulated.

\begin{example*}
\readdata{\foo}{words.dat}
\psset{yunit=.2mm,xunit=4mm}
\begin{pspicture}(-2,-50)(20,250)
\psaxes[axesstyle=frame,dy=50\psyunit,
  Dy=50,tickstyle=bottom,
  fillcolor=gray,fillstyle=solid](1,1)(18,229)
\dataplot[plotstyle=line,linecolor=white]{\foo}
\end{pspicture}
\end{example*}

\PST\ is not designed to be a fully-fledged business graphics package;
its plotting functions are really for simple scientific plots
only. However, it should be clear that the lower-level \PST\ macros,
and \TeX's programmability, make it a good basis for whatever
graphing is needed. 
We conclude this section with a crude pie chart, with the macros and 
some of the data used to create it; note that only
segments above a certain size are labelled --- providing a sensible
label for all elements would involve considerably more care.
\mbox{Denis} \mbox{Girou} has written a generalised pie-chart and bar
chart creation package for \PST\ (under
revision at the time of writing), which can produce very professional
results.

\newcommand\lang[4]{% name, value, percentage, color
 \setcounter{thisval}{\value{lastval}}
 \addtocounter{thisval}{#3}
 \pswedge[fillcolor=#4]{1}{\thelastval}{\thethisval}%
 \setcounter{thishalf}{((\value{thisval}-\value{lastval})/2)+\value{lastval}}
 \ifnum#3>200\rput(1.3;\thethishalf){#1}\fi
 \setcounter{lastval}{\value{thisval}}
}
\bgroup\psset{unit=2.5}
\centerline{\begin{pspicture}(-1.3,-1.3)(1.3,1.3)
\psset{fillstyle=solid}
\degrees[10000]
\SpecialCoor
\setcounter{lastval}{0}
\lang{Romanian}{1}{3}{green}
\lang{Czech}{2}{6}{blue}
\lang{Bulgarian}{4}{11}{green}
\lang{Japanese}{4}{11}{palegreen}
\lang{Dutch}{7}{20}{black}
\lang{Norwegian}{20}{56}{cyan}
\lang{Greek}{26}{73}{magenta}
\lang{Swedish}{34}{95}{lightgray}
\lang{Danish}{46}{129}{white}
\lang{French}{83}{232}{pink}
\lang{Latin}{146}{409}{wheat}
\lang{Russian}{243}{680}{white}
\lang{Italian}{391}{1093}{gray}
\lang{German}{508}{1421}{lightblue}
\lang{unknown}{599}{1676}{red}
\lang{English}{1462}{4085}{yellow}
\end{pspicture}}
\egroup
\begin{sverbatim}
\usepackage{calc,pstcol}
\newcommand{\lang}[4]{% name, value, proportion of
                      % 10000, colour
 \setcounter{thisval}{\value{lastval}}
 \addtocounter{thisval}{#3}
 \pswedge[fillcolor=#4]{1}{\thelastval}{\thethisval}%
 \setcounter{thishalf}{((\value{thisval}-
                           \value{lastval})/2)+
                             \value{lastval}}
 \ifnum#3>200\rput(1.3;\thethishalf){#1}\fi
 \setcounter{lastval}{\value{thisval}}
}
\psset{fillstyle=solid}
\degrees[10000]
\SpecialCoor
\setcounter{lastval}{0}
\lang{Romanian}{1}{3}{green}
\lang{Czech}{2}{6}{blue}
...
\lang{German}{508}{1421}{lightblue}
\lang{unknown}{599}{1676}{red}
\lang{English}{1462}{4085}{yellow}
\end{sverbatim}

\section{\protect\PST\ programming examples}\label{PSTprog}
In the following pictures, we attempt to show some of the range of
\PST\ possibilities, demonstrate the advantages of using a programming
language for drawing pictures, and explore the various tools for
simplifying and modularizing the code to make it more readable. We
are especially glad to acknowledge Denis Girou for his input to this
section, both in personal exchanges and in published examples.

In the first picture, a kite drawing from a child's book of colours and
shapes, notice how the tail is drawn as a curved node connection
between two points, and the bunting is added as labels on that
connection. Use of the node feature means that the calculation of the
line and positions along it are left entirely to
\PST.  It is also worth recalling the basic \PS\ premise that objects
are opaque unless otherwise stated; this means that we can draw a blue
background to the whole picture, and then overlay solid blocks of
colour for the shapes. Some parts of the picture have a regular,
repeating, feature, and we take advantage of this to
draw the rays of sun using the \Lcs{multido} macro; note that we use a
\TeX\ group to localize the effect of the \Lcs{psset} which changes colour
and style.
\verbfile{kite.tex}
%\end{multicols}
\begin{center}
\vspace*{1.5ex}
  \input kite.tex
\vspace*{1.5ex}
\end{center}
%\begin{multicols}{2}
In the next child's picture, we again take advantage of the strikeout
nature of \PS\ blocks of solid colour to draw the cat head as a whole
circle, and superimpose the wall (and on top of that the bricks) so
that we do not worry about creating a precise wedge of just
over a semicircle. \Lcs{rput} is used extensively to place objects at an
angle.  The writing on the bricks demonstrates the importance of
understanding the reference point of objects that are placed. Since
the bricks and their legends are drawn \emph{after} the graffito, they
partly obscure it.  We group objects of similar characteristics
together, and use \TeX's standard grouping to set \PST\ values for the
items in that group. We also break the picture into different
elements, describe each in a separate macro, and group them into
high-level objects.  This technique allows us to built up a library of
objects, and serves to make the final picture description considerably
more readable. The cat sitting on its portion of wall sets its size
according to a parameter, allowing us to reproduce it several times at
different sizes; note how the \Lcs{rput} command resets the coordinate
system, so that the cat is drawn relative to the position of the \Lcs{rput}.

\verbfile{cat.tex}
%\end{multicols}
\vspace*{1.5ex}
\begin{center}
  \input cat.tex
\end{center}
\vspace*{1.5ex}
%\begin{multicols}{2}
The third complete picture is more complex, a
circuit diagram. We have
chosen to make this by programming a small language
for circuit diagrams, which implements the actions
\Lcs{Battery},
\Lcs{Resistor}, \Lcs{Switch} and
\Lcs{Inductor}, with the movement commands
\Lcs{Up},
\Lcs{Down}
\Lcs{Left}, and
\Lcs{Right}  in the spirit of \textsf{pic}.
Thus the final part of the input is quite simple,
apart from the node connection and label commands which are used
in their normal way (some care is needed to consider the angles
at which connection lines leave and join each node).

\begin{sverbatim}
\Up{1}
\Battery{A}
\Up{1}
\Right{2}
\Resistor{B}
\Right{1}
\Down{.3}
\Inductor{C}
\Down{.5}
\Left{1}
\Switch{D}
\ncangle[angleA=90,angleB=180,armB=0]{A}{B}
\ncangle[angleA=0,angleB=90,armB=0]{B}{C}
\ncput[ref=l]{~~~$i=i_{\mbox{max}}(1-w^{-t/3})$}
\ncangle[angleA=-90,armB=0,angleB=0]{C}{D}
\ncangle[angleA=180,armB=0,angleB=-90]{D}{A}
\nput{180}{A}{10V}
\nput{90}{B}{R}
\nput{0}{C}{3mH}
\nput{270}{D}{S}
\end{sverbatim}

\makeatletter 
\newdimen\CurX
\newdimen\CurY \newdimen\Cir@temp
\newcount\Cir@direction % 0 right, 1 left, 2 up, 3 down
\Cir@direction0
\def\SetX#1{\CurX=#1pt}
\def\SetY#1{\CurY=#1pt}
\def\ShowDirection{\typeout{Direction:
 \ifcase\Cir@direction right\or left\or up\or down\fi,
    now at (\strip@pt\CurX,\strip@pt\CurY)}%
}
\def\ShowXY{\message{(\strip@pt\CurX,\strip@pt\CurY)}}

\def\Down#1{\advance\CurY  by -#1\p@\Cir@direction3\ShowDirection}
\def\Up#1{\advance\CurY  by #1\p@\Cir@direction2\ShowDirection}
\def\Left#1{\advance\CurX by -#1\p@\Cir@direction1\ShowDirection}
\def\Right#1{\advance\CurX by #1\p@\Cir@direction0\ShowDirection}
\def\MyBox#1#2{% width,height
 \pssetlength{\Cir@temp}{#1}%
 \rule{\Cir@temp}{\z@}%
 \pssetlength{\Cir@temp}{#2}%
 \rule{\z@}{\Cir@temp}%
}
\def\Point#1{%
\rput(\strip@pt\CurX,\strip@pt\CurY){\pnode{#1}}%
}
\def\Switch#1{%
\message{[Switch] #1}\ShowXY
\relax
\ifcase\Cir@direction % right
   \rput[b](\strip@pt\CurX,\strip@pt\CurY){\rnode[b]{#1}{%
   \psline(.5,.4)%
   \psarc{<-}{.4}{-10}{70}%
   \MyBox{.5}{.4}%
   }}%
   \advance\CurX by .5\p@
\or % left
   \advance\CurX by -.5\p@
   \rput[b](\strip@pt\CurX,\strip@pt\CurY){\rnode[b]{#1}{%
   \psline(0,0)(.5,.4)%
   \psarc{<-}{.4}{-10}{70}%
   \MyBox{.5}{.4}%
  }}%
\fi
}

\def\Battery#1{%
\message{[Battery] #1}\ShowXY
\relax
\ifcase\Cir@direction % right
   \rput[r](\strip@pt\CurX,\strip@pt\CurY){\rnode{#1}{%
     \psline(0,-.4)(0,.4)%
     \psline(.2,-.2)(.2,.2)%
     \MyBox{.2}{.8}%
    }}%
   \advance\CurX by .2\p@
\or % left
   \advance\CurX by -.2\p@
   \rput[r](\strip@pt\CurX,\strip@pt\CurY){\rnode{#1}{%
     \psline(0,-.4)(0,.4)%
     \psline(.2,-.2)(.2,.2)%
     \MyBox{.2}{.8}%
    }}%
\or % up
   \advance\CurY by .2\p@
   \rput[b](\strip@pt\CurX,\strip@pt\CurY){\rnode{#1}{%
     \psline(.1,.2)(.9,.2)%
     \psline(0.3,0)(0.7,0)%
     \MyBox{1}{.2}%
    }}%
\or % down
   \rput[b](\strip@pt\CurX,\strip@pt\CurY){\rnode{#1}{%
     \psline(-.4,0)(.4,0)%
     \psline(-.2,-.2)(.2,-.2)%
     \MyBox{1}{.2}%
    }}%
   \advance\CurY by -.2\p@
\fi
}

\def\Resistor{\message{[Resistor]}\ShowXY
  \@ifnextchar[{\@ResInd}{\@ResInd[1]{pszigzag}}}
\def\Inductor{\message{[Inductor]}\ShowXY
  \@ifnextchar[{\@ResInd}{\@ResInd[1]{pscoil}}}

\def\@ResInd[#1]#2#3{%
 \ifcase\Cir@direction % right
   \rput[l](\strip@pt\CurX,\strip@pt\CurY){\rnode{#3}{%
   \csname #2\endcsname[coilarm=.01,coilwidth=.3](0,.15)(#1,.15)%
   \MyBox{#1}{.3}%
    }}%
   \advance\CurX by #1\p@
 \or % left
   \advance\CurX by -#1\p@
   \rput[l](\strip@pt\CurX,\strip@pt\CurY){\rnode{#3}{%
   \csname #2\endcsname[coilarm=.01,coilwidth=.3](0,.15)(#1,.15)%
   \MyBox{#1}{.3}%
    }}%
 \or % up
   \rput[b](\strip@pt\CurX,\strip@pt\CurY){\rnode{#3}{%
   \csname #2\endcsname[coilarm=.01,coilwidth=.3](.15,0)(.15,#1)%
   \MyBox{.3}{#1}%
    }}%
   \advance\CurY by #1\p@
 \or % down
   \advance\CurY by -#1\p@
   \rput[b](\strip@pt\CurX,\strip@pt\CurY){\rnode{#3}{%
   \csname #2\endcsname[coilarm=.01,coilwidth=.3](.15,0)(.15,#1)%
   \MyBox{.3}{#1}%
    }}%
 \fi
}
\makeatother

\begin{pspicture}(5,5)
\SetX{1}
\Up{1}
\Battery{A}
\Up{1}
\Right{2}
\Resistor{B}
\Right{1}
\Down{.3}
\Inductor{C}
\Down{.5}
\Left{1}
\Switch{D}
\ncangle[angleA=90,angleB=180,armB=0]{A}{B}
\ncangle[angleA=0,angleB=90,armB=0]{B}{C}
\ncput[ref=l]{~~~$i=i_{\mbox{max}}(1-w^{-t/3})$}
\ncangle[angleA=-90,armB=0,angleB=0]{C}{D}
\ncangle[angleA=180,armB=0,angleB=-90]{D}{A}
\nput{180}{A}{10V}
\nput{90}{B}{R}
\nput{0}{C}{3mH}
\nput{270}{D}{S}
\end{pspicture}

The new commands are implemented in terms of a current $x$ and $y$
coordinate, which is changed by the movement commands. Thus \Lcs{Down} is
defined (simplified) in the following code:

\begin{sverbatim}
\newcommand{\Down}[1]{%
  \setcounter{CurY}}{-#1}%
  \def{Cirdirection}{3}%
  }
\end{sverbatim}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{figure*}[t!]
\centerline{\includegraphics{map.eps}}
\caption{Autocad picture converted to \protect\PST\ macros}
\label{PSTacad}
\end{figure*}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

After each movement the current direction of movement is recorded,
since this affects how we draw the new objects. These have a switch
(which we have simplified in the following code example\footnote{since
we possibly want sizes to be real numbers, \Lcs{CurX} and \Lcs{CurY}
are in fact \TeX\ dimensions, which we convert back to numbers before
use.})  to check direction. The plain \TeX{} \Lcs{ifcase} command is
used to perform a 4-way switch between directions. The definition of
the resistor is:

\begin{sverbatim}
\newcommand{\Resistor}[1]{%
 \ifcase\Cirdirection % right
   \rput[l](\CurX,\CurY){\rnode{#1}{%
   \pszigzag[coilarm=.01,coilwidth=.3](0,.15)(1,.15)%
   \MyBox{1}{.3}}}%
   \addtocounter{CurX}{1}%
 \or % left
   \addtocounter{CurX}{-1}%
   \rput[l](\CurX,\CurY){\rnode{#1}{%
   \pszigzag[coilarm=.01,coilwidth=.3](0,.15)(1,.15)%
   \MyBox{1}{.3}}}%
 \or % up
   \rput[b](\CurX,\CurY){\rnode{#1}{%
   \pszigzag[coilarm=.01,coilwidth=.3](.15,0)(.15,1)%
   \MyBox{.3}{1}}}%
   \addtocounter{CurY}{1}%
 \or % down
   \addtocounter{CurY}{-1}%
   \rput[b](\CurX,\CurY){\rnode{#1}{%
   \pszigzag[coilarm=.01,coilwidth=.3](.15,0)(.15,1)%
   \MyBox{.3}{1}}}%
 \fi
}
\end{sverbatim}

The macro \Lcs{MyBox} is very important; since by itself \Lcs{pszigzag} takes
no space, it will create a node with no width or height, and
connectors will go right to the middle. Therefore we put in some
\LaTeX\ struts with the \Lcs{rule} command, to create an invisible box
around the zigzag. The \PST\ units are converted to normal \TeX\
lengths using \Lcs{pssetlength}.

\begin{sverbatim}
\newlength{\Cirtemp}
\newcommand{\MyBox}[2]{% width,height
 \pssetlength{\Cirtemp}{#1}%
 \rule{\Cirtemp}{0pt}%
 \pssetlength{\Cirtemp}{#2}%
 \rule{0pt}{\Cirtemp}%
}
\end{sverbatim}


Our final example takes \PST\ into another subject area, that of
cartography. The map in Figure~\ref{PSTacad} is created from
an Autocad DXF file; this time the 36
polygons, comprising 9619 separate line segments, were converted
(using a simple \emph{ad hoc} conversion program) to a separate
coordinate data file for each polygon. The overall map description
consists simply of 36 lines of the form:
\begin{sverbatim}
\ProcessVector{moh174}
\ProcessVector{moh170}
\end{sverbatim}
Since the number of coordinates is so large, many of the \PST\ tools
which can read the files (like \Lcs{fileplot}) run out of \TeX\ memory;
however, for purely graphical objects like polygons, we have the 
more efficient and less memory-intensive option of writing
Encapsulated \PS\ files on the fly, so we instantiate the
\Lcs{ProcessVector} lines with the definition:
\begin{sverbatim}
\newcommand{\ProcessVector}[1]{%
 \PSTtoEPS{#1.eps}{\fileplot{#1.dat}}
 \rput(0,0){\includegraphics{#1.eps}}%
}
\end{sverbatim}
The command \Lcs{PSTtoEPS} takes two arguments, a filename, and any
pure \PST\ commands (\ie not text). Instead of embedding the necessary
\PS\ as \Lcs{special}s in the \TeX\ output, a \PS\ file is written
directly.

Using the very simple top level \Lcs{ProcessVector} command means that the
master file is easily hand-edited; since the Autocad file identifies
the polygons by their `layer' (the map is a set of contour lines), we
are able to set the fill colour separately for each layer, and so
produce the more traditional map.
\end{Article}