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