You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
8.1 KiB
229 lines
8.1 KiB
% Copyright 2008 by Mark Wibrow
|
|
%
|
|
% This file may be distributed and/or modified
|
|
%
|
|
% 1. under the LaTeX Project Public License and/or
|
|
% 2. under the GNU Public License.
|
|
%
|
|
% See the file doc/generic/pgf/licenses/LICENSE for more details.
|
|
|
|
\newdimen\pgflsystemstep
|
|
\newcount\c@pgf@lsystem@iteration
|
|
|
|
\newif\ifpgf@lsystem@randomize@step
|
|
\newif\ifpgf@lsystem@randomize@angle
|
|
|
|
\pgfkeys{/pgf/lindenmayer system/.cd,%
|
|
step/.code={\pgfmathsetlength\pgflsystemstep{#1}},%
|
|
randomize step percent/.code={%
|
|
\pgfmathparse{#1}%
|
|
\let\pgflsystemrandomizesteppercent=\pgfmathresult%
|
|
\ifdim\pgfmathresult pt=0pt\relax%
|
|
\pgf@lsystem@randomize@stepfalse%
|
|
\else%
|
|
\pgf@lsystem@randomize@steptrue%
|
|
\fi%
|
|
},%
|
|
left angle/.code={\pgfmathparse{#1}\let\pgflsystemleftangle=\pgfmathresult},%
|
|
right angle/.code={\pgfmathparse{#1}\let\pgflsystemrightangle=\pgfmathresult},%
|
|
angle/.style={/pgf/lindenmayer system/left angle=#1, /pgf/lindenmayer system/right angle=#1},%
|
|
randomize angle percent/.code={%
|
|
\pgfmathparse{#1}%
|
|
\let\pgflsystemrandomizeanglepercent=\pgfmathresult%
|
|
\ifdim\pgfmathresult pt=0pt\relax%
|
|
\pgf@lsystem@randomize@anglefalse%
|
|
\else%
|
|
\pgf@lsystem@randomize@angletrue%
|
|
\fi%
|
|
}%
|
|
}%
|
|
|
|
\pgfkeys{/pgf/lindenmayer system/.cd,
|
|
step=5pt,%
|
|
randomize step percent=0,%
|
|
angle=90,%
|
|
randomize angle percent=0%
|
|
}%
|
|
|
|
\long\def\pgfdeclarelindenmayersystem#1#2{%
|
|
\pgfutil@ifundefined{pgf@lsystem@#1}%
|
|
{%
|
|
\begingroup%
|
|
\edef\pgf@lsystem@name{#1}%
|
|
\expandafter\global\expandafter\let\csname pgf@lsystem@#1\endcsname=\pgf@lsystem@name%
|
|
\let\symbol=\pgf@lsystem@symbol%
|
|
\let\rule=\pgf@lsystem@rule%
|
|
#2%
|
|
\endgroup%
|
|
}%
|
|
{\pgferror{Lindenmayer system `#1' is already defined}}%
|
|
}%
|
|
|
|
\def\pgf@lsystem@symbol#1#2{%
|
|
\expandafter\gdef\csname pgf@lsystem@\pgf@lsystem@name @symbol@#1\endcsname{#2}%
|
|
}%
|
|
|
|
\def\pgf@lsystem@rule#1{\expandafter\pgf@lsystem@rule@#1\pgf@stop}%
|
|
\def\pgf@lsystem@rule@#1{\def\pgf@lsystem@rule@head{#1}\pgf@lsystem@rule@@}%
|
|
\def\pgf@lsystem@rule@@#1->{% Now some `fooling around' to deal with unwanted spaces.
|
|
\let\pgf@lsystem@rule@body=\pgfutil@empty%
|
|
\pgfutil@ifnextchar x{\pgf@lsystem@rule@@@}{\pgf@lsystem@rule@@@}}%
|
|
\def\pgf@lsystem@rule@@@#1{%
|
|
\ifx#1\pgf@stop%
|
|
\expandafter\global\expandafter\let%
|
|
\csname pgf@lsystem@\pgf@lsystem@name @rule@\pgf@lsystem@rule@head\endcsname=\pgf@lsystem@rule@body%
|
|
\else%
|
|
\edef\pgf@lsystem@rule@body{\pgf@lsystem@rule@body#1}%
|
|
\expandafter\pgf@lsystem@rule@@@%
|
|
\fi%
|
|
}%
|
|
|
|
\def\pgflindenmayersystem#1#2#3{%
|
|
\begingroup%
|
|
\edef\pgf@lsystem@name{#1}%
|
|
\edef\pgf@lsystem@axiom{#2}%
|
|
\pgfmathtruncatemacro\pgf@lsystem@order{#3}%
|
|
%
|
|
\let\pgf@lsystem@current@symbol=\relax%
|
|
%
|
|
\c@pgf@lsystem@iteration=0\relax%
|
|
%
|
|
\ifnum\pgf@lsystem@order=0\relax%
|
|
\expandafter\pgf@lsystem@draw\pgf@lsystem@axiom\pgf@stop
|
|
\let\pgf@lsystem@next=\pgf@lsystem@end%
|
|
\else%
|
|
\let\pgf@lsystem@next=\pgf@lsystem@run%
|
|
\fi%
|
|
\expandafter\pgf@lsystem@next\pgf@lsystem@axiom\pgf@lsystem@stop%
|
|
}%
|
|
|
|
\def\pgf@lsystem@run#1{%
|
|
\ifx#1\pgf@lsystem@stop%
|
|
\def\pgf@lsystem@token{\pgf@lsystem@stop}%
|
|
\let\pgf@lsystem@next=\pgf@lsystem@end%
|
|
\else%
|
|
\ifx#1\pgf@stop%
|
|
\advance\c@pgf@lsystem@iteration by-1\relax%
|
|
\let\pgf@system@token=\pgfutil@empty%
|
|
\let\pgf@lsystem@next=\pgf@lsystem@run%
|
|
\else%
|
|
% Does #1 appear on the RHS of a rule...?
|
|
\expandafter\let\expandafter\pgf@lsystem@token\expandafter=%
|
|
\csname pgf@lsystem@\pgf@lsystem@name @rule@#1\endcsname%
|
|
\ifx\pgf@lsystem@token\relax%
|
|
% ...nope. So draw it straight away.
|
|
\pgf@lsystem@draw#1\pgf@stop%
|
|
\let\pgf@lsystem@token=\pgfutil@empty%
|
|
\else%
|
|
% ...yep. So, if the order has been reached draw the LHS
|
|
% immediately. Otherwise add the LHS to the token stream
|
|
% and continue.
|
|
\advance\c@pgf@lsystem@iteration by1\relax%
|
|
\ifnum\c@pgf@lsystem@iteration=\pgf@lsystem@order%
|
|
\expandafter\pgf@lsystem@draw\pgf@lsystem@token \pgf@stop%
|
|
\advance\c@pgf@lsystem@iteration by-1\relax%
|
|
\let\pgf@lsystem@token=\pgfutil@empty%
|
|
\else%
|
|
\expandafter\def\expandafter\pgf@lsystem@token\expandafter{\pgf@lsystem@token \pgf@stop}%
|
|
\fi%
|
|
\fi%
|
|
\let\pgf@lsystem@next=\pgf@lsystem@run%
|
|
\fi%
|
|
\fi%
|
|
\expandafter\pgf@lsystem@next\pgf@lsystem@token}%
|
|
|
|
\def\pgf@lsystem@end#1\pgf@lsystem@stop{\endgroup}%
|
|
|
|
\def\pgf@lsystem@draw#1{%
|
|
\ifx#1\pgf@stop%
|
|
\let\pgf@lsystem@next=\relax%
|
|
\else%
|
|
\expandafter\let\expandafter\pgf@lsystem@current@symbol\expandafter=%
|
|
\csname pgf@lsystem@\pgf@lsystem@name @symbol@#1\endcsname%
|
|
\ifx\pgf@lsystem@current@symbol\relax% Try a default symbol.
|
|
\expandafter\let\expandafter\pgf@lsystem@current@symbol\expandafter=%
|
|
\csname pgf@lsystem@symbol@default@#1\endcsname%
|
|
\fi%
|
|
\let\pgf@lsystem@next=\pgf@lsystem@@draw%
|
|
\fi%
|
|
\pgf@lsystem@next}%
|
|
|
|
\def\pgf@lsystem@@draw{%
|
|
\edef\pgflsystemcurrentstep{\the\pgflsystemstep}%
|
|
\let\pgflsystemcurrentrightangle=\pgflsystemrightangle%
|
|
\let\pgflsystemcurrentrightangle=\pgflsystemleftangle%
|
|
\pgf@lsystem@current@symbol%
|
|
\pgf@lsystem@draw}%
|
|
|
|
\expandafter\def\csname
|
|
pgf@lsystem@symbol@default@F\endcsname{\pgflsystemdrawforward}%
|
|
\expandafter\def\csname
|
|
pgf@lsystem@symbol@default@f\endcsname{\pgflsystemmoveforward}%
|
|
\expandafter\def\csname
|
|
pgf@lsystem@symbol@default@+\endcsname{\pgflsystemturnleft}%
|
|
\expandafter\def\csname
|
|
pgf@lsystem@symbol@default@-\endcsname{\pgflsystemturnright}%
|
|
\expandafter\def\csname
|
|
pgf@lsystem@symbol@default@[\endcsname{\pgflsystemsavestate}%
|
|
\expandafter\def\csname
|
|
pgf@lsystem@symbol@default@]\endcsname{\pgflsystemrestorestate}%
|
|
|
|
\def\pgflsystemradonmizestep{%
|
|
\ifpgf@lsystem@randomize@step%
|
|
\pgfmathrand%
|
|
\pgf@x=\pgflsystemrandomizesteppercent pt\relax%
|
|
\pgf@x=\pgfmathresult\pgf@x%
|
|
\divide\pgf@x by20\relax%
|
|
\advance\pgf@x by\pgflsystemstep\relax%
|
|
\edef\pgflsystemcurrentstep{\the\pgf@x}%
|
|
\else%
|
|
\edef\pgflsystemcurrentstep{\the\pgflsystemstep}%
|
|
\fi%
|
|
}%
|
|
|
|
\def\pgflsystemdrawforward{%
|
|
\pgflsystemradonmizestep
|
|
\pgftransformxshift{+\pgflsystemcurrentstep}%
|
|
\pgfpathlineto{\pgfpointorigin}}%
|
|
|
|
\def\pgflsystemmoveforward{%
|
|
\pgflsystemradonmizestep
|
|
\pgftransformxshift{+\pgflsystemcurrentstep}%
|
|
\pgfpathmoveto{\pgfpointorigin}}%
|
|
|
|
\def\pgflsystemranomizerightangle{%
|
|
\ifpgf@lsystem@randomize@angle%
|
|
\pgf@x=\pgflsystemrandomizeanglepercent pt\relax%
|
|
\divide\pgf@x by20\relax%
|
|
\pgfmathrand%
|
|
\pgf@x=\pgfmathresult\pgf@x%
|
|
\advance\pgf@x by\pgflsystemrightangle pt\relax%
|
|
\edef\pgflsystemcurrentrightangle{\pgfmath@tonumber{\pgf@x}}%
|
|
\else%
|
|
\let\pgflsystemcurrentrightangle=\pgflsystemrightangle%
|
|
\fi%
|
|
}%
|
|
|
|
\def\pgflsystemranomizeleftangle{%
|
|
\ifpgf@lsystem@randomize@angle%
|
|
\pgf@x=\pgflsystemrandomizeanglepercent pt\relax%
|
|
\divide\pgf@x by20\relax%
|
|
\pgfmathrand%
|
|
\pgf@x=\pgfmathresult\pgf@x%
|
|
\advance\pgf@x by\pgflsystemleftangle pt\relax%
|
|
\edef\pgflsystemcurrentleftangle{\pgfmath@tonumber{\pgf@x}}%
|
|
\else%
|
|
\let\pgflsystemcurrentleftangle=\pgflsystemleftangle%
|
|
\fi%
|
|
}%
|
|
|
|
\def\pgflsystemturnright{%
|
|
\pgflsystemranomizerightangle
|
|
\pgftransformrotate{-\pgflsystemcurrentrightangle}}%
|
|
|
|
\def\pgflsystemturnleft{%
|
|
\pgflsystemranomizeleftangle
|
|
\pgftransformrotate{\pgflsystemcurrentleftangle}}%
|
|
|
|
\def\pgflsystemsavestate{\begingroup}%
|
|
\def\pgflsystemrestorestate{\endgroup\pgfpathmoveto{\pgfpointorigin}}%
|
|
|