sawine@9
|
1 |
% pgftree.tex
|
sawine@9
|
2 |
% Version 1.1, 25 Dec 2009
|
sawine@9
|
3 |
|
sawine@9
|
4 |
% Copyright 2009 by David Chiang
|
sawine@9
|
5 |
|
sawine@9
|
6 |
% This program is free software; you can redistribute it and/or modify
|
sawine@9
|
7 |
% it under the terms of the GNU General Public License as published by
|
sawine@9
|
8 |
% the Free Software Foundation; either version 2 of the License, or
|
sawine@9
|
9 |
% (at your option) any later version.
|
sawine@9
|
10 |
|
sawine@9
|
11 |
% This program is distributed in the hope that it will be useful,
|
sawine@9
|
12 |
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
sawine@9
|
13 |
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
sawine@9
|
14 |
% GNU General Public License for more details.
|
sawine@9
|
15 |
|
sawine@9
|
16 |
% You should have received a copy of the GNU General Public License along
|
sawine@9
|
17 |
% with this program; if not, write to the Free Software Foundation, Inc.,
|
sawine@9
|
18 |
% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
sawine@9
|
19 |
|
sawine@9
|
20 |
% New in version 1.1:
|
sawine@9
|
21 |
% - major restructuring to not do arbitrary nesting of subpicture environments
|
sawine@9
|
22 |
% - sideways trees
|
sawine@9
|
23 |
|
sawine@9
|
24 |
% To do:
|
sawine@9
|
25 |
% - trees with all leaves at same level
|
sawine@9
|
26 |
% - if \nodename does not exist as desired, wrap inside a rectangle node
|
sawine@9
|
27 |
% - don't use pgfsubpic internals
|
sawine@9
|
28 |
|
sawine@9
|
29 |
\newdimen\levelsep \levelsep=30pt
|
sawine@9
|
30 |
\newdimen\subtreesep \subtreesep=2pt
|
sawine@9
|
31 |
|
sawine@9
|
32 |
\def\leveldirection{down}
|
sawine@9
|
33 |
\def\siblingdirection{right}
|
sawine@9
|
34 |
|
sawine@9
|
35 |
% definitions of growing directions
|
sawine@9
|
36 |
\def\pgftree@levelshift{\csname pgftree@levelshift@\leveldirection\endcsname}
|
sawine@9
|
37 |
\def\pgftree@parentanchor{\csname pgftree@parentanchor@\leveldirection\endcsname}
|
sawine@9
|
38 |
\def\pgftree@childanchor{\csname pgftree@childanchor@\leveldirection\endcsname}
|
sawine@9
|
39 |
% these assume that the current subpicture is the child
|
sawine@9
|
40 |
\def\pgftree@presiblingshift{\csname pgftree@presiblingshift@\siblingdirection\endcsname}
|
sawine@9
|
41 |
\def\pgftree@postsiblingshift{\csname pgftree@postsiblingshift@\siblingdirection\endcsname}
|
sawine@9
|
42 |
|
sawine@9
|
43 |
\def\pgftree@levelshift@down{\pgfpoint{0}{-\levelsep}}
|
sawine@9
|
44 |
\def\pgftree@parentanchor@down{south}
|
sawine@9
|
45 |
\def\pgftree@childanchor@down{north}
|
sawine@9
|
46 |
|
sawine@9
|
47 |
\def\pgftree@levelshift@up{\pgfpoint{0}{\levelsep}}
|
sawine@9
|
48 |
\def\pgftree@parentanchor@up{north}
|
sawine@9
|
49 |
\def\pgftree@childanchor@up{south}
|
sawine@9
|
50 |
|
sawine@9
|
51 |
\def\pgftree@levelshift@right{\pgfpoint{\levelsep}{0}}
|
sawine@9
|
52 |
\def\pgftree@parentanchor@right{east}
|
sawine@9
|
53 |
\def\pgftree@childanchor@right{west}
|
sawine@9
|
54 |
|
sawine@9
|
55 |
\def\pgftree@levelshift@left{\pgfpoint{-\levelsep}{0}}
|
sawine@9
|
56 |
\def\pgftree@parentanchor@left{west}
|
sawine@9
|
57 |
\def\pgftree@childanchor@left{east}
|
sawine@9
|
58 |
|
sawine@9
|
59 |
\def\pgftree@presiblingshift@right{\pgf@process{\pgf@x-\pgf@subpicminx \advance\pgf@x\subtreesep \pgf@y 0pt}}
|
sawine@9
|
60 |
\def\pgftree@postsiblingshift@right{\pgf@process{\pgf@x\pgf@subpicmaxx \pgf@y 0pt}}
|
sawine@9
|
61 |
|
sawine@9
|
62 |
\def\pgftree@presiblingshift@left{\pgf@process{\pgf@x-\pgf@subpicmaxx \advance\pgf@x-\subtreesep \pgf@y 0pt}}
|
sawine@9
|
63 |
\def\pgftree@postsiblingshift@left{\pgf@process{\pgf@x\pgf@subpicminx \pgf@y 0pt}}
|
sawine@9
|
64 |
|
sawine@9
|
65 |
\def\pgftree@presiblingshift@up{\pgf@process{\pgf@x 0pt \pgf@y-\pgf@subpicminy \advance\pgf@y\subtreesep}}
|
sawine@9
|
66 |
\def\pgftree@postsiblingshift@up{\pgf@process{\pgf@x 0pt \pgf@y\pgf@subpicmaxy}}
|
sawine@9
|
67 |
|
sawine@9
|
68 |
\def\pgftree@presiblingshift@down{\pgf@process{\pgf@x 0pt \pgf@y-\pgf@subpicmaxy \advance\pgf@y-\subtreesep}}
|
sawine@9
|
69 |
\def\pgftree@postsiblingshift@down{\pgf@process{\pgf@x 0pt \pgf@y\pgf@subpicminy}}
|
sawine@9
|
70 |
|
sawine@9
|
71 |
% for convenience if you are using \pgftree directly
|
sawine@9
|
72 |
\def\drawnode#1{\pgfnode{rectangle}{base}{#1}{\nodename}{\pgfusepath{discard}}}
|
sawine@9
|
73 |
\def\drawedge{%
|
sawine@9
|
74 |
\pgfpathmoveto{\pgfpointanchor{\parentnodename}{\pgftree@parentanchor}}%
|
sawine@9
|
75 |
\pgfpathlineto{\pgfpointanchor{\nodename}{\pgftree@childanchor}}%
|
sawine@9
|
76 |
\pgfusepath{stroke}}
|
sawine@9
|
77 |
|
sawine@9
|
78 |
% local variables that we need to assign to inside a \pgfforeach
|
sawine@9
|
79 |
\newdimen\pgftree@childx
|
sawine@9
|
80 |
\newdimen\pgftree@savechildx
|
sawine@9
|
81 |
\newdimen\pgftree@childy
|
sawine@9
|
82 |
\newdimen\pgftree@savechildy
|
sawine@9
|
83 |
\newcount\pgftree@childi
|
sawine@9
|
84 |
\newcount\pgftree@savechildi
|
sawine@9
|
85 |
|
sawine@9
|
86 |
%%% \pgftree{subtree}
|
sawine@9
|
87 |
|
sawine@9
|
88 |
\def\pgftree#1{%
|
sawine@9
|
89 |
\def\nodename{r}%
|
sawine@9
|
90 |
#1%
|
sawine@9
|
91 |
\pgfplacesubpicture
|
sawine@9
|
92 |
}
|
sawine@9
|
93 |
|
sawine@9
|
94 |
%%% \pgfsubtree{root}{subtrees}
|
sawine@9
|
95 |
% The first argument draws the root node using PGF/TikZ commands.
|
sawine@9
|
96 |
% The node must be named \nodename.
|
sawine@9
|
97 |
|
sawine@9
|
98 |
% The second argument is an even-length sequence of tokens.
|
sawine@9
|
99 |
% Token 2n-1 in the sequence draws the nth edge. It should draw an edge from \parentnodename to \nodename.
|
sawine@9
|
100 |
% Token 2n in the sequence draws the nth subtree. Its root must be named \nodename.
|
sawine@9
|
101 |
|
sawine@9
|
102 |
\pgfnewsubpicture{children}
|
sawine@9
|
103 |
\newdimen\pgftree@lastchildx
|
sawine@9
|
104 |
\newdimen\pgftree@lastchildy
|
sawine@9
|
105 |
|
sawine@9
|
106 |
\def\pgfsubtree#1#2{%
|
sawine@9
|
107 |
\let\parentnodename\nodename
|
sawine@9
|
108 |
\pgftree@savechildx=\pgftree@childx
|
sawine@9
|
109 |
\pgftree@savechildy=\pgftree@childy
|
sawine@9
|
110 |
\pgftree@savechildi=\pgftree@childi
|
sawine@9
|
111 |
% Build subpicture with all the children and their subtrees
|
sawine@9
|
112 |
{\pgftree@childx=0pt%
|
sawine@9
|
113 |
\pgftree@childy=0pt%
|
sawine@9
|
114 |
\pgftree@childi=0%
|
sawine@9
|
115 |
\process@children #2}%
|
sawine@9
|
116 |
\begin{pgfsubpicture}%
|
sawine@9
|
117 |
% Create node
|
sawine@9
|
118 |
#1%
|
sawine@9
|
119 |
\ifnum\pgftree@childi>0%
|
sawine@9
|
120 |
% Place children
|
sawine@9
|
121 |
% move down \levelsep
|
sawine@9
|
122 |
{\pgftransformshift{\pgftree@levelshift}%
|
sawine@9
|
123 |
% center so that parent is midway between origins of first and last children
|
sawine@9
|
124 |
\pgftransformshift{\pgfpointscale{-0.5}{\pgfqpoint{\the\pgftree@childx}{\the\pgftree@childy}}}%
|
sawine@9
|
125 |
\pgfplacesubpicture}%
|
sawine@9
|
126 |
% Draw the edges
|
sawine@9
|
127 |
{\pgftree@childi=0%
|
sawine@9
|
128 |
\process@edges #2}%
|
sawine@9
|
129 |
\fi
|
sawine@9
|
130 |
\end{pgfsubpicture}%
|
sawine@9
|
131 |
\global\pgftree@childi=\pgftree@savechildi
|
sawine@9
|
132 |
\global\pgftree@childx=\pgftree@savechildx
|
sawine@9
|
133 |
\global\pgftree@childy=\pgftree@savechildy
|
sawine@9
|
134 |
}
|
sawine@9
|
135 |
|
sawine@9
|
136 |
\def\process@children{%
|
sawine@9
|
137 |
\pgfutil@ifnextchar\egroup
|
sawine@9
|
138 |
{% No more children, step back to origin of last child
|
sawine@9
|
139 |
\global\pgftree@childx\pgftree@lastchildx
|
sawine@9
|
140 |
\global\pgftree@childy\pgftree@lastchildy
|
sawine@9
|
141 |
\global\pgftree@childi\pgftree@childi
|
sawine@9
|
142 |
\ifnum\pgftree@childi>0%
|
sawine@9
|
143 |
\pgfrestoresubpicture{children}% pass children back to caller
|
sawine@9
|
144 |
\fi
|
sawine@9
|
145 |
}%
|
sawine@9
|
146 |
{\@process@children}%
|
sawine@9
|
147 |
}
|
sawine@9
|
148 |
\def\@process@children#1#2{% #1 is the edge, #2 is the child
|
sawine@9
|
149 |
% Build the current child
|
sawine@9
|
150 |
{\edef\nodename{\parentnodename-\the\pgftree@childi}%
|
sawine@9
|
151 |
#2}%
|
sawine@9
|
152 |
\begin{pgfsubpicture}%
|
sawine@9
|
153 |
% Place current child
|
sawine@9
|
154 |
\ifnum\pgftree@childi>0% the first child is always at 0
|
sawine@9
|
155 |
\pgftree@presiblingshift \global\advance\pgftree@childx\pgf@x \global\advance\pgftree@childy\pgf@y
|
sawine@9
|
156 |
\fi
|
sawine@9
|
157 |
{\pgftransformshift{\pgfqpoint{\the\pgftree@childx}{\the\pgftree@childy}}%
|
sawine@9
|
158 |
\pgfplacesubpicture}%
|
sawine@9
|
159 |
\global\pgftree@lastchildx\pgftree@childx
|
sawine@9
|
160 |
\global\pgftree@lastchildy\pgftree@childy
|
sawine@9
|
161 |
\pgftree@postsiblingshift \global\advance\pgftree@childx\pgf@x \global\advance\pgftree@childy\pgf@y
|
sawine@9
|
162 |
% Save the augmented row of children back into "children"
|
sawine@9
|
163 |
\end{pgfsubpicture}
|
sawine@9
|
164 |
\ifnum\pgftree@childi>0%
|
sawine@9
|
165 |
\pgfmergesubpicture{children}
|
sawine@9
|
166 |
\else
|
sawine@9
|
167 |
\pgfsavesubpicture{children}%
|
sawine@9
|
168 |
\fi
|
sawine@9
|
169 |
\advance\pgftree@childi by 1%
|
sawine@9
|
170 |
\process@children
|
sawine@9
|
171 |
}
|
sawine@9
|
172 |
|
sawine@9
|
173 |
\def\process@edges{%
|
sawine@9
|
174 |
\pgfutil@ifnextchar\egroup
|
sawine@9
|
175 |
{}%
|
sawine@9
|
176 |
{\@process@edges}%
|
sawine@9
|
177 |
}
|
sawine@9
|
178 |
\def\@process@edges#1#2{%
|
sawine@9
|
179 |
\edef\nodename{\parentnodename-\the\pgftree@childi}%
|
sawine@9
|
180 |
#1%
|
sawine@9
|
181 |
\advance\pgftree@childi by 1%
|
sawine@9
|
182 |
\process@edges
|
sawine@9
|
183 |
}
|
sawine@9
|
184 |
|
sawine@9
|
185 |
\def\subtreeof#1{%
|
sawine@9
|
186 |
% the subpicture which contains a node also contains exactly its subtree
|
sawine@9
|
187 |
\csname pgf@sh@pi@#1\endcsname
|
sawine@9
|
188 |
}
|