summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/randomwalk
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-09-20 22:31:39 +0000
committerKarl Berry <karl@freefriends.org>2015-09-20 22:31:39 +0000
commit6dfa7943f147ffdfe5efdcb565b537bc91129e95 (patch)
tree391ecf22fdab020f51736958951596edca0707d4 /Master/texmf-dist/source/latex/randomwalk
parentb2ea7dce029df59615ef6bd98e335672bd219171 (diff)
randomwalk (20sep15)
git-svn-id: svn://tug.org/texlive/trunk@38418 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/randomwalk')
-rw-r--r--Master/texmf-dist/source/latex/randomwalk/randomwalk.dtx309
1 files changed, 181 insertions, 128 deletions
diff --git a/Master/texmf-dist/source/latex/randomwalk/randomwalk.dtx b/Master/texmf-dist/source/latex/randomwalk/randomwalk.dtx
index 06e6614f44f..0bb83e0d80a 100644
--- a/Master/texmf-dist/source/latex/randomwalk/randomwalk.dtx
+++ b/Master/texmf-dist/source/latex/randomwalk/randomwalk.dtx
@@ -16,6 +16,7 @@
\RequirePackage{expl3}
\documentclass[full]{l3doc}
\usepackage{randomwalk}
+\AtBeginDocument{\chgrand[seed = 411500]\rand}
\usepackage{amsmath}
\begin{document}
\DocInput{randomwalk.dtx}
@@ -24,11 +25,11 @@
% \fi
%
%^^A The date here also is in \ProvidesExplPackage, and in the copyright.
-% \def\fileversion{v0.3}
-% \def\filedate{2015/03/03}
+% \def\fileversion{v0.4}
+% \def\filedate{2015/09/20}
%
% \title{The \pkg{randomwalk} package: \\
-% customizable random walks using TikZ\thanks{This file describes version
+% customizable random walks\thanks{This file describes version
% \fileversion, last revised \filedate.}}
% \author{Bruno Le Floch\thanks{E-mail blflatex@gmail.com}}
% \date{Released on \filedate}
@@ -40,14 +41,15 @@
%
% \begin{abstract}
%
-% The \pkg{randomwalk} package draws random walks using TikZ. The
+% The \pkg{randomwalk} package draws random walks. The
% following parameters can be customized:
% \begin{itemize}
% \item The number of steps, of course.
% \item The length of the steps, either a fixed length, or a length
-% taken at random from a given set.
-% \item The angle of each step, either taken at random from a given
-% set, or uniformly distributed.
+% taken uniformly at random from a given list.
+% \item The angle of each step, either taken uniformly at random
+% from a given list, or uniformly distributed between $0$~and
+% $360$ degrees.
% \end{itemize}
%
% \end{abstract}
@@ -55,16 +57,21 @@
%
% \section{How to use \pkg{randomwalk}}
%
+% \newcommand{\examplei}
+% {\RandomWalk {number = 200, length = {4pt, 10pt}}}
+% \newcommand{\exampleii}
+% {\RandomWalk {number = 100, angles = {0,60,120,180,240,300}, degree}}
+% \newcommand{\exampleiii}
+% {\RandomWalk {number = 50, length = 1ex, angles = {0,24,48,-24,-48}, degree, angles-relative}}
% \begin{function}{\RandomWalk}
-% The \pkg{randomwalk} package has exactly one user command:
+% The \pkg{randomwalk} package has a single user command:
% \cs{RandomWalk}, which takes a list of key-value pairs as its
-% argument. A few examples:
-% \begin{verbatim}
-% \RandomWalk {number = 200, length = {4pt, 10pt}}
-% \RandomWalk {number = 100, angles = {0,60,120,180,240,300}, degree}
-% \RandomWalk {number = 100, length = 1ex,
-% angles = {0,24,48,-24,-48}, degree, angles-relative}
-% \end{verbatim}
+% argument. A few examples are given in Figures~\ref{examplei}, \ref{exampleii}, and~\ref{exampleiii}:
+% \begin{quote}\ttfamily
+% \detokenize\expandafter{\examplei}\\
+% \detokenize\expandafter{\exampleii}\\
+% \detokenize\expandafter{\exampleiii}
+% \end{quote}
% Here is a list of all the keys, and their meaning:
% \begin{itemize}
% \item \texttt{number}: the number of steps (default \(10\))
@@ -89,30 +96,26 @@
%
% \begin{figure}
% \begin{center}
-% \framebox{\RandomWalk {number = 200, length = {4pt, 10pt}}}
-% \caption{The result of \texttt{RandomWalk\ \{number = 200,
-% length = \{4pt, 10pt\}\}}: a \(200\) steps long walk, where
-% each step has one of two lengths.}
+% \framebox{\examplei}
+% \caption{\label{examplei}A \(200\) steps long
+% walk, where each step has one of two lengths:
+% \texttt{\detokenize\expandafter{\examplei}}}
% \end{center}
% \end{figure}
%
% \begin{figure}
% \begin{center}
-% \framebox{\RandomWalk{number = 100, angles =
-% {0, 60, 120, 180, 240, 300}, degrees}}
-% \caption{The result of \texttt{\string\RandomWalk\ \{number =
-% 100, angles = \{0, 60, 120, 180, 240, 300\}, degrees\}}: angles
-% are constrained.}
+% \framebox{\exampleii}
+% \caption{\label{exampleii}A walk with constrained angles:
+% \texttt{\detokenize\expandafter{\exampleii}}}
% \end{center}
% \end{figure}
%
% \begin{figure}
% \begin{center}
-% \framebox{\RandomWalk {number = 100, length = 1ex, angles =
-% {0, 24, 48, -24, -48}, degree, angles-relative}}
-% \caption{A last example: \texttt{\string\RandomWalk\ \{number =
-% 100, length = 1ex, angles = \{0, 24, 48, -24, -48\},
-% degree, angles-relative\}}}
+% \framebox{\exampleiii}
+% \caption{\label{exampleiii}A last example, with small relative
+% angles: \texttt{\detokenize\expandafter{\exampleiii}}}
% \end{center}
% \end{figure}
%
@@ -132,27 +135,28 @@
% \end{macrocode}
%
% \begin{macrocode}
-\RequirePackage{expl3}[2012/08/14]
+\RequirePackage{expl3}[2015/09/11]
\ProvidesExplPackage
- {randomwalk.sty} {2015/03/03} {0.3} {Customizable random walks using TikZ}
-\RequirePackage{xparse}[2012/08/14]
+ {randomwalk.sty} {2015/09/20} {0.4} {Customizable random walks}
+\RequirePackage{xparse}[2015/09/11]
% \end{macrocode}
%
-% I use some \LaTeXe{} packages: \pkg{TikZ}, for figures, and \pkg{lcg}
-% for random numbers.
+% Load \pkg{pgfcore} for figures.
% \begin{macrocode}
-\RequirePackage{tikz}
+\RequirePackage{pgfcore}
% \end{macrocode}
%
-% \pkg{lcg} needs to know the smallest and biggest random numbers that
-% it should produce, which we take to be $0$ and $\cs{c_@@_lcg_last_int}
+% Load \pkg{lcg} for random numbers.
+% It needs to know the smallest and biggest random numbers that
+% should be produced, which we take to be $0$ and $\cs{c_@@_lcg_last_int}
% = 2^{31}-2$. It will then store them in \cs{c@lcg@rand}: the |\c@| is
% there because of how \LaTeXe{} defines counters. To make it clear that
% |\c| has a very special meaning here, I do not follow \LaTeX3 naming
% conventions. Also of note is that I use \cs{cr@nd} in \cs{@@_walk:}.
%
% It seems that the \pkg{lcg} package has to be loaded after the
-% document class, hence we do it \cs{AtBeginDocument}.
+% document class, hence we do it \cs{AtBeginDocument}. Also worth noting
+% is the call to \cs{rand}, which avoids some very odd bug.
% \begin{macrocode}
\int_const:Nn \c_@@_lcg_last_int { \c_max_int - \c_one }
\AtBeginDocument
@@ -164,7 +168,7 @@
counter = lcg@rand
]
{ lcg }
- \rand % This \rand avoids some very odd bug.
+ \rand
}
% \end{macrocode}
%
@@ -219,56 +223,74 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}[aux]{\l_@@_old_x_fp, \l_@@_old_y_fp}
-% \begin{variable}[aux]{\l_@@_new_x_fp, \l_@@_new_y_fp}
-% Coordinates of the two ends of each step: each \cs{draw} statement
-% goes from the |_old| point to the |_new| point. See
-% \cs{@@_step_draw:}.
+% \begin{variable}[aux]{\l_@@_x_dim, \l_@@_y_dim}
+% Current coordinates: each \cs{pgfpathlineto} statement
+% goes from the previous value of these to the next. See
+% \cs{@@_walk_step:}.
% \begin{macrocode}
-\fp_new:N \l_@@_old_x_fp
-\fp_new:N \l_@@_old_y_fp
-\fp_new:N \l_@@_new_x_fp
-\fp_new:N \l_@@_new_y_fp
+\dim_new:N \l_@@_x_dim
+\dim_new:N \l_@@_y_dim
% \end{macrocode}
% \end{variable}
-% \end{variable}
%
% \begin{variable}[aux]{\l_@@_angles_seq, \l_@@_lengths_seq}
-% Sequences containing all allowed angles and lengths.
+% Sequences containing all allowed angles and lengths, as
+% floating point numbers.
% \begin{macrocode}
\seq_new:N \l_@@_angles_seq
\seq_new:N \l_@@_lengths_seq
% \end{macrocode}
% \end{variable}
%
-% \subsection{How the key-value list is treated}
+% \subsection{User command and key-value list}
%
% \begin{macro}{\RandomWalk, \randomwalk:n}
-% The user command \cs{RandomWalk}, based on the code-level
+% The user command \cs{RandomWalk} is based on the code-level
% command \cs{randomwalk:n}, which simply does the setup and calls
% the internal macro \cs{@@_walk:}.
% \begin{macrocode}
\DeclareDocumentCommand \RandomWalk { m }
- { \randomwalk:n { #1 } }
+ { \randomwalk:n {#1} }
\cs_new_protected:Npn \randomwalk:n #1
{
- \@@_set_defaults:
- \keys_set:nn { randomwalk } { #1 }
+ \@@_setup_defaults:
+ \keys_set:nn { randomwalk } {#1}
\@@_walk:
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\@@_set_defaults:}
-% Currently, the package treats the length of steps, and the angle,
+% We introduce the keys for the package.
+% \begin{macrocode}
+\keys_define:nn { randomwalk }
+ {
+ number .value_required:n = true ,
+ length .value_required:n = true ,
+ angles .value_required:n = true ,
+ number .int_set:N = \l_@@_step_number_int ,
+ length .code:n = { \@@_setup_length:n {#1} } ,
+ angles .code:n = { \@@_setup_angles:n {#1} } ,
+ degree .bool_set:N = \l_@@_degrees_bool ,
+ degrees .bool_set:N = \l_@@_degrees_bool ,
+ angles-relative .bool_set:N = \l_@@_relative_angles_bool ,
+ revert-random .bool_set:N = \l_@@_revert_random_bool ,
+ }
+% \end{macrocode}
+%
+% \subsection{Setup}
+%
+% \begin{macro}[aux]{\@@_setup_defaults:}
+% The package treats the length of steps, and the angle,
% completely independently. The function \cs{@@_next_length:}
% contains the action that decides the length of the next step, while
% the function \cs{@@_next_angle:} pertains to the angle.
%
-% \cs{@@_set_defaults:} sets the default values before processing the
-% user's key-value input.
+% \cs{@@_setup_defaults:} sets the default values before processing the
+% user's key-value input. This also sets initial values of variables
+% that currently cannot be altered through keys, because it might be
+% good to provide keys for their initial values too later on.
% \begin{macrocode}
-\cs_new:Npn \@@_set_defaults:
+\cs_new_protected_nopar:Npn \@@_setup_defaults:
{
\int_set:Nn \l_@@_step_number_int {10}
\cs_gset_protected_nopar:Npn \@@_next_angle:
@@ -277,102 +299,133 @@
{ \fp_set:Nn \l_@@_length_fp {10} }
\bool_set_false:N \l_@@_revert_random_bool
\bool_set_false:N \l_@@_relative_angles_bool
+ \fp_zero:N \l_@@_angle_fp
+ \fp_zero:N \l_@@_length_fp
+ \dim_zero:N \l_@@_x_dim
+ \dim_zero:N \l_@@_y_dim
}
% \end{macrocode}
% \end{macro}
%
-% We introduce the keys for the package.
+% \begin{macro}[aux]{\@@_setup_length:n}
+% Convert each item in the comma list into a floating point, then
+% define \cs{@@_next_length:} to set \cs{l_@@_length_fp} to a random
+% floating point in the list.
% \begin{macrocode}
-\keys_define:nn { randomwalk }
+\cs_new_protected:Npn \@@_setup_length:n #1
{
- number .value_required: ,
- length .value_required: ,
- angles .value_required: ,
- number .int_set:N = \l_@@_step_number_int ,
- length .code:n =
+ \seq_set_split:Nnn \l_@@_lengths_seq { , } {#1}
+ \seq_set_map:NNn \l_@@_lengths_seq
+ \l_@@_lengths_seq { \dim_to_fp:n {##1} }
+ \cs_gset_protected_nopar:Npn \@@_next_length:
{
- \seq_set_split:Nnn \l_@@_lengths_seq { , } {#1}
- \seq_set_map:NNn \l_@@_lengths_seq
- \l_@@_lengths_seq { \dim_to_fp:n {##1} }
- \cs_gset_protected_nopar:Npn \@@_next_length:
- {
- \@@_get_rand_seq_item:NN
- \l_@@_lengths_seq \l_@@_internal_tl
- \fp_set:Nn \l_@@_length_fp { \l_@@_internal_tl }
- }
- } ,
- angles .code:n =
+ \@@_get_rand_seq_item:NN
+ \l_@@_lengths_seq \l_@@_internal_tl
+ \fp_set:Nn \l_@@_length_fp { \l_@@_internal_tl }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_setup_angles:n}
+% Two complications compared to \cs{@@_setup_length:n}. First, the
+% angle can be given in radians rather than degrees: then add |rad|
+% after the randomly chosen value (in principle it would be better to
+% convert angles once and for all at the beginning, but that
+% interacts in a complicated way with the fact that keys can be given
+% in any order). Second, angles can be relative, in which case we
+% use \cs{fp_add:Nn} to take the last angle into account.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_setup_angles:n #1
+ {
+ \seq_set_split:Nnn \l_@@_angles_seq { , } {#1}
+ \seq_set_map:NNn \l_@@_angles_seq
+ \l_@@_angles_seq { \fp_to_tl:n {##1} }
+ \cs_gset_protected_nopar:Npn \@@_next_angle:
{
- \seq_set_split:Nnn \l_@@_angles_seq { , } {#1}
- \seq_set_map:NNn \l_@@_angles_seq
- \l_@@_angles_seq { \fp_to_tl:n {##1} }
- \cs_gset_protected_nopar:Npn \@@_next_angle:
- {
- \@@_get_rand_seq_item:NN
- \l_@@_angles_seq \l_@@_internal_tl
- \bool_if:NF \l_@@_degrees_bool
- { \tl_put_right:Nn \l_@@_internal_tl { rad } }
- \bool_if:NTF \l_@@_relative_angles_bool
- { \fp_add:Nn } { \fp_set:Nn }
- \l_@@_angle_fp { \l_@@_internal_tl }
- }
- } ,
- degree .bool_set:N = \l_@@_degrees_bool ,
- degrees .bool_set:N = \l_@@_degrees_bool ,
- angles-relative .bool_set:N = \l_@@_relative_angles_bool ,
- revert-random .bool_set:N = \l_@@_revert_random_bool ,
+ \@@_get_rand_seq_item:NN
+ \l_@@_angles_seq \l_@@_internal_tl
+ \bool_if:NF \l_@@_degrees_bool
+ { \tl_put_right:Nn \l_@@_internal_tl { rad } }
+ \bool_if:NTF \l_@@_relative_angles_bool
+ { \fp_add:Nn } { \fp_set:Nn }
+ \l_@@_angle_fp { \l_@@_internal_tl }
+ }
}
% \end{macrocode}
+% \end{macro}
%
% \subsection{Drawing}
%
% \begin{macro}[aux]{\@@_walk:}
-% We are ready to define \cs{@@_walk:}, which draws a \pkg{TikZ}
+% We are ready to define \cs{@@_walk:}, which draws a \pkg{pgf}
% picture of a random walk with the parameters set up by the
-% \texttt{keys}. We reset all the coordinates to zero originally.
-% Then draw the relevant \pkg{TikZ} picture by repeatedly calling
-% \cs{@@_step_draw:}.
+% \texttt{keys}. We reset coordinates to zero originally.
+% Then draw the relevant \pkg{pgf} picture by repeatedly calling
+% \cs{@@_walk_step:}.
% \begin{macrocode}
-\cs_new:Npn \@@_walk:
+\cs_new_protected_nopar:Npn \@@_walk:
{
- \begin{tikzpicture}
- \fp_zero:N \l_@@_angle_fp
- \fp_zero:N \l_@@_length_fp
- \fp_zero:N \l_@@_old_x_fp
- \fp_zero:N \l_@@_old_y_fp
- \fp_zero:N \l_@@_new_x_fp
- \fp_zero:N \l_@@_new_y_fp
- \prg_replicate:nn { \l_@@_step_number_int }
- { \@@_step_draw: }
- \bool_if:NF \l_@@_revert_random_bool
- { \int_gset_eq:NN \cr@nd \cr@nd }
- \end{tikzpicture}
+ \@@_walk_start:
+ \prg_replicate:nn { \l_@@_step_number_int }
+ { \@@_walk_step: }
+ \bool_if:NF \l_@@_revert_random_bool
+ { \int_gset_eq:NN \cr@nd \cr@nd }
+ \@@_walk_stop:
}
% \end{macrocode}
% \cs{cr@nd} is internal to the lcg package.
% \end{macro}
%
-% \begin{macro}[aux]{\@@_step_draw:}
-% \cs{@@_step_draw:} calls \cs{@@_next_length:} and
+% \begin{macro}[aux]{\@@_walk_start:, \@@_walk_line:, \@@_walk_stop:}
+% These functions encapsulate all of the \pkg{pgf}-related code. The
+% \texttt{start} function begins the pgfpicture environment and
+% starts a path at position (x,y). The \texttt{line} function adds
+% to the path a line from the previous position to the new (x,y).
+% The \texttt{stop} function draws the path constructed by
+% \cs{@@_walk_step:} and ends the pgfpicture environment.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_walk_start:
+ {
+ \begin{pgfpicture}
+ \pgfpathmoveto
+ { \pgfpoint { \l_@@_x_dim } { \l_@@_y_dim } }
+ }
+\cs_new_protected_nopar:Npn \@@_walk_line:
+ {
+ \pgfpathlineto
+ { \pgfpoint { \l_@@_x_dim } { \l_@@_y_dim } }
+ }
+\cs_new_protected_nopar:Npn \@@_walk_stop:
+ {
+ \pgfusepath { stroke }
+ \end{pgfpicture}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_walk_step:}
+% \cs{@@_walk_step:} calls \cs{@@_next_length:} and
% \cs{@@_next_angle:} to determine the length and angle of the new
% step. This is then converted to cartesian coordinates and added to
-% the previous end-point. Finally, we call \pkg{TikZ}'s \cs{draw} to
-% produce a line from the |_old| to the |_new| point.
+% the previous end-point. Finally, we call \pkg{pgf}'s \cs{pgfpathlineto} to
+% produce a line to the new point.
% \begin{macrocode}
-\cs_new:Npn \@@_step_draw:
+\cs_new_protected_nopar:Npn \@@_walk_step:
{
\@@_next_length:
\@@_next_angle:
- \fp_set_eq:NN \l_@@_old_x_fp \l_@@_new_x_fp
- \fp_set_eq:NN \l_@@_old_y_fp \l_@@_new_y_fp
- \fp_add:Nn \l_@@_new_x_fp
- { \l_@@_length_fp * cosd \l_@@_angle_fp }
- \fp_add:Nn \l_@@_new_y_fp
- { \l_@@_length_fp * sind \l_@@_angle_fp }
- \draw ( \fp_to_dim:N \l_@@_old_x_fp ,
- \fp_to_dim:N \l_@@_old_y_fp )
- -- ( \fp_to_dim:N \l_@@_new_x_fp ,
- \fp_to_dim:N \l_@@_new_y_fp );
+ \dim_add:Nn \l_@@_x_dim
+ {
+ \fp_to_dim:n
+ { \l_@@_length_fp * cosd ( \l_@@_angle_fp ) }
+ }
+ \dim_add:Nn \l_@@_y_dim
+ {
+ \fp_to_dim:n
+ { \l_@@_length_fp * sind ( \l_@@_angle_fp ) }
+ }
+ \@@_walk_line:
}
% \end{macrocode}
% \end{macro}