~tex-sx/tex-sx/development

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
\immediate\write18{tex spath.dtx}
\documentclass{ltxdoc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{morefloats}
\usepackage{tikz}
\usepackage{spath}
\usepackage[numbered]{hypdoc}
\definecolor{lstbgcolor}{rgb}{0.9,0.9,0.9} 
 
\usepackage{listings}
\lstloadlanguages{[LaTeX]TeX}
\lstset{breakatwhitespace=true,breaklines=true,language=TeX}
 
\usepackage{fancyvrb}

\newenvironment{example}
  {\VerbatimEnvironment
   \begin{VerbatimOut}{example.out}}
  {\end{VerbatimOut}
   \begin{center}
   \setlength{\parindent}{0pt}
   \fbox{\begin{minipage}{.9\linewidth}
     \lstset{breakatwhitespace=true,breaklines=true,language=TeX,basicstyle=\small}
     \lstinputlisting[]{example.out}
   \end{minipage}}

   \fbox{\begin{minipage}{.9\linewidth}
     \input{example.out}
   \end{minipage}}
\end{center}
}

\providecommand*{\url}{\texttt}
\GetFileInfo{spath.sty}

\title{The \textsf{spath} Package: Documentation}
\author{Andrew Stacey \\ \url{stacey@math.ntnu.no}}
\date{\fileversion~from \filedate}

\begin{document}

\maketitle

\section{Introduction}

The \texttt{spath} library is an object-oriented interface to the \emph{soft path} system of PGF.
It allows one to save, manipulate, and use \emph{soft paths} in a more general way than is currently easy with TikZ/PGF.
This library was developed for use with the \texttt{calligraphy} package since that required various path manipulations that would have been hard to do otherwise.

There are several steps in the TikZ/PGF system between writing \Verb+\draw (0,0) -- (1,0);+ and a line appearing in the document.
The command just given is a TikZ command.
The TikZ frontend translates that into PGF commands.
These are then processed into a \emph{soft path}.
The soft path can be manipulated further before being ``baked'' into a hard path which is then written out into the output file via an appropriate driver.

A soft path is a simple object.
It consists of a list of tokens of the form \Verb+\pgfsyssoftpath@<something>token{x pt}{y pt}+\footnote{Except for the \Verb+closepath+ token which omits the final \Verb+token+.}.
There are only a handful of possible \Verb+<something>+s.
It is therefore quite straightforward to manipulate these paths in an orderly fashion.
However, the PGF code does not provide a particular method for doing complicated manipulations on these paths.
This library introduces some such methods.

One thing to note at the outset is that this library makes no attempt to optimise the code and so if the soft path is very long, it will take a considerable time to do any of these manipulations.
The PGF soft path system does have some optimisations to handle this.

\section{Usage}

Using this library is relatively straightforward.
After loading TikZ/PGF, simply \Verb+\usepackage{spath}+ in the preamble.
A typical example of using the library is in the following example.

\begin{example}
\begin{tikzpicture}
\useasboundingbox (-1,1) rectangle (2,-2);
\path[save path=\tmppath] (-1,0) -- (0,0) .. controls +(1,0) and +(1,0) .. (1,1);
\pgfoonew \mypath=new spath(\tmppath)
\mypath.prepare()
\mypath.reverse path()
\mypath.use path with tikz(draw)
\mypath.translate path(,0cm,-2cm)
\mypath.at least three()
\mypath.split path by real length(\fpath,\mpath,1)
\begin{scope}[ultra thick]
\fpath.taper out()
\fpath.use path with tikz(fill)
\mpath.split path by real length(\mmpath,\epath,-1)
\epath.reverse path()
\epath.taper out()
\epath.use path with tikz(fill)
\mmpath.use path with tikz(draw)
\end{scope}
\end{tikzpicture}
\end{example}

In this example, we start by defining a path in the usual TikZian manner.
However, instead of doing something with the path, we save it.
This saves the raw path as a macro.
In order to use this library on that path, we have to convert it into an \Verb+spath+ object.
This is done with the next line, starting \Verb+\pgfoonew+ (note the spacing: there must be no space after the \Verb+=+).
This command declares \Verb+\mypath+ to be an instance of the \Verb+spath+ class and initialises it with the path stored in \Verb+\tmppath+.
(For scoping reasons, we can't define a PGF key to be given to the original \Verb+\path+ command to do this in one go.)
This can now be manipulated with the \Verb+spath+ methods.
We shall explain the actual methods later so shall not go into detail now.

\section{Attributes and Methods}

The \texttt{spath} library defines two classes: the \Verb+spath+ and \Verb+spath component+.
The \Verb+spath+ is a soft path, the \Verb+spath component+ is an array of \Verb+spath+ objects.

\subsection{The \texttt{spath} Object}

The following is a list of the attributes that an \Verb+spath+ object has.
The class operates on a lazy system: attributes are not automatically worked out so they will not have values initially.
However, as soon as you do something that needs one to have a value it will be computed.

\begin{itemize}
\item \Verb+path+

This holds the actual soft path.

\item \Verb+length+

This (when initialised) is the length of the soft path in number of soft path tokens.

\item \Verb+real length+

This is the number of actual drawing tokens in the soft path; that is, the number of \Verb+lineto+ and \Verb+curveto+ tokens.

(This ought to also count \Verb+rect+, but I don't know of a TikZ command that actually produces a \Verb+rect+.)

\item \Verb+number of components+

This is the number of components of the path when divided up by \Verb+moveto+s.
It is actually the number of \Verb+moveto+s so successive \Verb+moveto+s will each count.

\item \Verb+initial point+

This is the coordinates of the start of the path.
It is of the form \Verb+\pgfpoint{x coordinate}{y coordinate}+ so when executed will set \Verb+\pgf@x+ and \Verb+\pgf@y+ to the corresponding coordinates.

\item \Verb+final point+

This is the coordinates of the end of the path.

\item \Verb+first action+

This is the first drawing action on the path (that is, not the initial \Verb+moveto+).

\item \Verb+last action+

This is the last action on the path (which might be a \Verb+moveto+).

\item \Verb+prepared+

The attributes are not calculated initially, but are calculated as needed.
There is a method available for calculating them all in one fell swoop.
If this has been called, this attribute is set so that the path knows its attributes have all be computed and don't need to be computed again.

\item \Verb+taper line width+

When tapering a path, it is necessary to set both the current line width and a width to taper to.
This holds the latter.

\end{itemize}

The following is a list of the methods available for an \Verb+spath+ object with a brief explanation of what each does.
The contents of the parentheses are the arguments for the method.

\begin{itemize}
\item \Verb+spath(#1)+

This is the creator method, it is called automatically when the object is created.
The argument, if given, is a macro containing a soft path which is used to set the \Verb+path+ attribute.

\item \Verb+value(#1)+

This method inserts the value of the attribute passed to it into the token stream.

\item \Verb+set(#1,#2)+

This method sets the attribute passed to it as the first argument to the second argument.

\item \Verb+let(#1,#2)+

This method lets the attribute passed to it as the first argument to be the second argument.
The second argument ought to be a macro, therefore.

\item \Verb+get(#1,#2)+

This method assigns the second argument to the value of the attribute passed to it as the first argument.
The second argument ought to be a macro, therefore.

\item \Verb+show(#1)+

This method shows the value of the attribute in the logs.
It uses \Verb+\show+ internally.

\item \Verb+clone(#1)+

This method clones the \Verb+spath+ object into the macro passed as the argument. 

\item \Verb+translate path(#1,#2,#3)+

This method translates the path by \Verb+#2+ in the x-direction and \Verb+#3+ in the y-direction.
If \Verb+#1+ is not empty, it should be a macro which is used to store the translated object (it will be an \Verb+spath+ object).
If \Verb+#1+ is empty, the current object is modified.

\item \Verb+length()+

This method inserts the length of the path in the token stream, computing it if it is not already known.
(It is this computation which makes it differ from the \Verb+value+ method.)

\item \Verb+real length()+

This method inserts the real length of the path in the token stream, computing it if it is not already known.

\item \Verb+number of components()+

This method inserts the number of components of the path in the token stream, computing it if it is not already known.

\item \Verb+initial point()+

This method inserts the number of components of the path in the token stream, computing it if it is not already known.

\item \Verb+final point()+

This method inserts the number of components of the path in the token stream, computing it if it is not already known.

\item \Verb+reverse path(#1)+

This method reverses the soft path.
If the argument is given, the reverse path is stored in it as a new \Verb+spath+ object.
If not, the current path is modified.

\item \Verb+prepare()+

This fills out all the attributes.
Finding the information for an attribute involves ``walking'' along the path.
Therefore, if we're going to need more than one, it makes sense to do them all in one go.
Calling this method ensures that they are all filled in and does so more efficiently than calling each individually.

\item \Verb+at least three()+

One of the things that the \texttt{calligraphy} package wants to be able to do is taper a path.
To do this nicely, the path should have at least three drawing pieces.
This ensures that this is so by splitting it if it does not.
If it has one piece, it is split into three at the .3 and .7 marks.
If it has two pieces, each is split in half.

\item \Verb+taper out()+

This is used to taper a path.
In fact, it replaces the first drawing component by a simularted tapered path (actually the outline of the tapered path is returned).
The rest of the path is thrown away, so this should be used after the path has been split.

\item \Verb+split path by length(#1,#2,#3)+

This splits a path according to the length.
The first argument will be an \Verb+spath+ object corresponding to the first part of the path, the second the rest, and the third says how many tokens should be in the first part of the path.
Both pieces are ``proper'' paths, so the second will be given an initial \Verb+moveto+.

\item \Verb+split path by real length(#1,#2,#3)+

This is the same as \Verb+split path by length+ except that it uses the \Verb+real length+ as the criterion of when to split.

\item \Verb+split path by component(#1,#2,#3)+

This is the same as \Verb+split path by length+ except that it uses the \Verb+number of components+ as the criterion of when to split.

\item \Verb+split(#1,#2,#3)+

This is the method that actually does the splitting.
It depends on certain macros being set which the previous three methods initialise.
It should therefore not be called directly.
Consider it a ``private'' method.

\item \Verb+reprocess path()+

This reprocesses the path.
Some TikZ/PGF settings have implications for how a path is constructed (such as the \Verb+rounded corners+ option).
If these have changed since the path was originally defined, it might be reasonable to redraw the path under the new conditions.
This does so.

\item \Verb+set as current path()+

This replaces the current path by the path stored in this object.

\item \Verb+get from current path()+

This replaces the path stored in this object by the current path.

\item \Verb+use path(#1)+

This uses the path.
The argument should be one of the PGF usage commands: \Verb+draw+, \Verb+fill+, \Verb+clip+, or \Verb+discard+.

\item \Verb+use path with tikz(#1)+

This uses the path but in a TikZian way.
The argument should be a list of TikZ styles to be set for the path.
Imagine this as \Verb+\path[<options>] <path>;+.

\item \Verb+concatenate(#1,#2)+

This concatenates the path in the current object with that from another.
If the first argument is given (which should be a macro), the result will a new \Verb+spath+ object stored in that macro.
If not, the object will be modified itself.
Since paths start with a \Verb+moveto+, the concatenation will not be a continuous path. 

\item \Verb+concatenate with lineto(#1,#2)+

This concatenates the path as \Verb+concatenate+ does, except that the \Verb+moveto+ in the middle is replaced by a \Verb+lineto+.

\item \Verb+weld(#1,#2)+

This welds two paths together.
Welding is like concatenation except that the second path is translated so that its starting point is the final point of the first path (and the \Verb+moveto+ is removed).

\item \Verb+close()+

This closes the path.
\end{itemize}

\subsection{The \texttt{spath component} Object}

An \Verb+spath component+ object is an element in an array of \Verb+spath+ objects.
Each element contains an \Verb+spath+ object and pointers to the previous and successive components.

\begin{itemize}
\item \Verb+path+

This is the \Verb+spath+ object of the current element.

\item \Verb+next component+

This is the next \Verb+spath component+ object (if non-empty).

\item \Verb+previous component+

This is the previous \Verb+spath component+ object (if non-empty).
\end{itemize}

The methods for \Verb+spath component+s are as follows.

\begin{itemize}
\item \Verb+spath component(#1)+

This is the initialiser method.
The argument should be the previous component in the array.

\item \Verb+value(#1)+

This method, and the following ones, are exactly as in the \Verb+spath+ object.

\item \Verb+set(#1,#2)+
\item \Verb+let(#1,#2)+
\item \Verb+get(#1,#2)+
\item \Verb+show(#1)+
\item \Verb+set path(#1)+

This sets the \Verb+spath+ attribute of this object.

\item \Verb+apply to paths(#1,#2)+

This applies a method to all of the \Verb+spath+ objects in the array, starting with the current path and proceding to the next component, and so on.
The first argument is the method name, the second is any argument that is to be passed to that method.

\item \Verb+apply to previous paths(#1,#2)+

This applies a method to all of the \Verb+spath+ objects in the array, starting with the current path and proceding to the previous component, and so on.
\end{itemize}

There is an additional command for use when creating an array of \Verb+spath component+s.
This is \Verb+\spathsplit+.
It takes two arguments.
The first is a macro that will become the first component of an array of \Verb+spath component+s.
The second is a macro containing a soft path.
The soft path will be split into pieces according to its components (that is, at the \Verb+moveto+s) and stored in the array.
At the moment, the last component is (temporarily) available at the end of the split as the \Verb+\spath@this@component+ macro.


\end{document}