exercises/solutions/pgftree.tex
author Eugen Sawin <sawine@me73.com>
Sat, 19 May 2012 04:25:58 +0200
changeset 10 05bd6cb31abc
permissions -rw-r--r--
Final ex03.
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
}