diff options
author | Karl Berry <karl@freefriends.org> | 2014-01-26 22:14:21 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2014-01-26 22:14:21 +0000 |
commit | f743052d85acf7d676d00e1903db1806032ac9f6 (patch) | |
tree | 09ad4bdf5a9a5607a4727be3a8e7adcd23fe2662 | |
parent | fc11ec42903196eb886eff26e3c251aa47fdd8fb (diff) |
hobby
git-svn-id: svn://tug.org/texlive/trunk@32795 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/hobby/README (renamed from Master/texmf-dist/doc/latex/hobby/README.txt) | 0 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/hobby/hobby.pdf | bin | 0 -> 366952 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/hobby/hobby_doc.pdf | bin | 510319 -> 488046 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/hobby/hobby_doc.tex | 7 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/hobby/hobby.dtx | 242 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/hobby/hobby.code.tex | 66 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/hobby/pgflibraryhobby.code.tex | 19 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/hobby/tikzlibraryhobby.code.tex | 93 |
8 files changed, 350 insertions, 77 deletions
diff --git a/Master/texmf-dist/doc/latex/hobby/README.txt b/Master/texmf-dist/doc/latex/hobby/README index d48c4b90e17..d48c4b90e17 100644 --- a/Master/texmf-dist/doc/latex/hobby/README.txt +++ b/Master/texmf-dist/doc/latex/hobby/README diff --git a/Master/texmf-dist/doc/latex/hobby/hobby.pdf b/Master/texmf-dist/doc/latex/hobby/hobby.pdf Binary files differnew file mode 100644 index 00000000000..4f581c840cf --- /dev/null +++ b/Master/texmf-dist/doc/latex/hobby/hobby.pdf diff --git a/Master/texmf-dist/doc/latex/hobby/hobby_doc.pdf b/Master/texmf-dist/doc/latex/hobby/hobby_doc.pdf Binary files differindex 8a21dc7f065..c3b008ed70e 100644 --- a/Master/texmf-dist/doc/latex/hobby/hobby_doc.pdf +++ b/Master/texmf-dist/doc/latex/hobby/hobby_doc.pdf diff --git a/Master/texmf-dist/doc/latex/hobby/hobby_doc.tex b/Master/texmf-dist/doc/latex/hobby/hobby_doc.tex index fa5fa58087c..a00a4d525a0 100644 --- a/Master/texmf-dist/doc/latex/hobby/hobby_doc.tex +++ b/Master/texmf-dist/doc/latex/hobby/hobby_doc.tex @@ -9,6 +9,7 @@ \usepackage{fancyvrb} \usetikzlibrary{hobby,decorations.pathreplacing} \usepackage{listings} +\pgfplotsset{compat=1.9} \lstloadlanguages{[LaTeX]TeX} \lstset{breakatwhitespace=true,breaklines=true,language=TeX} @@ -58,7 +59,7 @@ \providecommand*{\url}{\texttt} \title{The \textsf{Hobby} package} \author{Andrew Stacey \\ \url{stacey@math.ntnu.no}} -\date{v1.2 from 2013/04/12} +\date{\hobbyVersion\ from\ \hobbyDate} \begin{document} \maketitle @@ -82,7 +83,7 @@ The resulting path produced with this ``quick'' version is not as ideal as that As this is intended as a simpler method, it does not (at present) admit the same level of customisation as the full implementation. The ``quick'' algorithm is described in full in Section~\ref{sec:quick}. -The full algorithm is implemented in \LaTeX3 with (almost\footnote{At the moment, \LaTeX3 lacks a \Verb+atan2+ function so \Verb+PGFMath+ is used to remedy that.}) no reference to TikZ or PGF. +The full algorithm is implemented in \LaTeX3 with no reference to TikZ or PGF. It makes extensive use of the \Verb+fp+ and \Verb+prop+ libraries for the computation steps. The TikZ library is simply a wrapper that takes the user's input, converts it into the right format for the \LaTeX3 code, and then calls that code to generate the path. The ``quick'' version does not use \LaTeX3 and relies instead on the \Verb+PGFMath+ library for the computation. @@ -420,7 +421,7 @@ This restores the named path and uses it with \Verb+<options>+ applied. This puts in place the code for saving the generated data to the \Verb+aux+ file. On subsequent runs, it uses the saved data rather than the current data. For a curve to make use of this, it has to be named via the \Verb+save Hobby path+ key. -So to regenerate the data, either delete the \Verb+aux+ file or remove the \Verb+save Hobby path+ key for one compilation run. +So to regenerate the data, either delete the \Verb+aux+ file, remove the \Verb+save Hobby path+ key for one compilation run, or issue the command \Verb+\HobbyDisableAux+ which disables writing paths to the \Verb+aux+ file (note that the paths will be regenerated on the run \emph{after} the first run with this command issued). \end{itemize} The options that can be applied are those that affect the rendering of the curve but not its generation. diff --git a/Master/texmf-dist/source/latex/hobby/hobby.dtx b/Master/texmf-dist/source/latex/hobby/hobby.dtx index c41e8f8d9fc..74ad06c13dd 100644 --- a/Master/texmf-dist/source/latex/hobby/hobby.dtx +++ b/Master/texmf-dist/source/latex/hobby/hobby.dtx @@ -110,7 +110,7 @@ and the derived files hobby.code.tex %</driver> % \fi % -% \CheckSum{3002} +% \CheckSum{3304} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -135,6 +135,7 @@ and the derived files hobby.code.tex % \providecommand*{\url}{\texttt} % \title{The \textsf{Hobby} package: code} % \author{Andrew Stacey \\ \url{stacey@math.ntnu.no}} +% \date{\hobbyVersion\ from\ \hobbyDate} % \maketitle % % @@ -165,17 +166,42 @@ and the derived files hobby.code.tex % % We declare all our variables. % +% Start with version and date, together with a check to see if we've been loaded twice (fail gracefully if so). +% +% \begin{macrocode} +\tl_clear:N \l_tmpa_tl +\tl_if_exist:NT \g__hobby_version +{ + \tl_set:Nn \l_tmpa_tl { + \ExplSyntaxOff + \tl_clear:N \l_tmpa_tl + \endinput + } +} +\tl_use:N \l_tmpa_tl + +\tl_new:N \g__hobby_version +\tl_new:N \g__hobby_date +\tl_set:Nn \g__hobby_version {1.4} +\tl_set:Nn \g__hobby_date {2014-01-21} +\DeclareDocumentCommand \hobbyVersion {} +{ + \tl_use:N \g__hobby_version +} +\DeclareDocumentCommand \hobbyDate {} +{ + \tl_use:N \g__hobby_date +} +% \end{macrocode} +% % The function for computing the lengths of the control points depends on three parameters. % These are set to \(a = \sqrt{2}\), \(b = 1/16\), and \(c = \frac{3 - \sqrt{5}}{2}\). % \begin{macrocode} \fp_new:N \g_hobby_parama_fp \fp_new:N \g_hobby_paramb_fp \fp_new:N \g_hobby_paramc_fp - \fp_gset:Nn \g_hobby_parama_fp {2^.5} - \fp_gset:Nn \g_hobby_paramb_fp {1/16} - \fp_gset:Nn \g_hobby_paramc_fp {(3-5^.5)/2} % \end{macrocode} % @@ -195,6 +221,18 @@ and the derived files hobby.code.tex % \end{macrocode} % \end{macro} % +% \begin{macro}{\l_hobby_save_aux_bool} +% \Verb+\l_hobby_save_aux_bool+ is \Verb+true+ if when saving paths then they should be saved to the \Verb+aux+ file. +% \begin{macrocode} +\bool_new:N \l_hobby_save_aux_bool +\bool_set_true:N \l_hobby_save_aux_bool +\DeclareDocumentCommand \HobbyDisableAux {} +{ + \bool_set_false:N \l_hobby_save_aux_bool +} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\l_hobby_points_array} % \Verb+\l_hobby_points_array+ is an array holding the specified points on the path. % In the \LaTeX3 code, a ``point'' is a token list of the form \Verb+x = <number>, y = <number>+. @@ -568,7 +606,7 @@ and the derived files hobby.code.tex (\array_get:Nn \l_hobby_points_y_array {#1 + 1}) - (\array_get:Nn \l_hobby_points_y_array {#1})} - \fp_atantwo:NNN \l_hobby_tempc_fp \l_hobby_tempb_fp \l_hobby_tempa_fp + \fp_set:Nn \l_hobby_tempc_fp { atan ( \l_hobby_tempb_fp, \l_hobby_tempa_fp ) } \fp_veclen:NVV \l_hobby_tempd_fp \l_hobby_tempa_fp \l_hobby_tempb_fp \array_push:Nx \l_hobby_angles_array {\fp_to_tl:N \l_hobby_tempc_fp} @@ -577,19 +615,6 @@ and the derived files hobby.code.tex % \end{macrocode} % \end{macro} % -% -% \begin{macro}{\fp_atantwo:NNN} -% Computes the angle of the point specified by the latter two arguments, storing the answer in the first. -% The inverse tangent function is not yet implemented in \LaTeX3 so for now we use the \Verb+pgfmath+ function. -% When this is implemented in \LaTeX3 this should be replaced. -% \begin{macrocode} -\cs_new:Nn \fp_atantwo:NNN { - \pgfmathparse{rad(atan2(\fp_use:N #3,\fp_use:N #2))} - \exp_args:NNo \fp_set:Nn #1 {\pgfmathresult} -} -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\fp_veclen:NVV} % Computes the length of the vector specified by the latter two arguments, storing the answer in the first. % \begin{macrocode} @@ -720,7 +745,7 @@ and the derived files hobby.code.tex \fp_if_undefined:NF \l_hobby_out_angle_fp { \fp_set:Nn \l_hobby_tempa_fp { \l_hobby_out_angle_fp - - \array_get:Nn \l_hobby_angles_array {0} } + - \array_get:Nn \l_hobby_angles_array {0}} % \end{macrocode} % We want to ensure that these angles lie in the range \((-\pi,\pi]\). % So if the angle is bigger than \(\pi\), we subtract \(2 \pi\). @@ -819,21 +844,12 @@ and the derived files hobby.code.tex % \end{macrocode} % Similarly, we check to see if the angle is less than \(-\pi\). % \begin{macrocode} - \fp_compare:nTF {\l_hobby_tempa_fp < -\c_pi_fp } + \fp_compare:nTF {\l_hobby_tempa_fp <= -\c_pi_fp } { \fp_add:Nn \l_hobby_tempa_fp {2 * \c_pi_fp} } {} % \end{macrocode} -% At the moment, the mixing of \Verb+pgfmath+ and \LaTeX3 that goes into computing the differences means that we can never get \Verb+\c_pi_fp+ so testing for equality is meaningless. -% However, when \Verb+atan2+ is implemented in \LaTeX3 then this might make sense again. -% -%^^A \fp_compare:nTF {\l_hobby_tempa_fp = -\c_pi_fp } -%^^A { -%^^A \fp_add:Nn \l_hobby_tempa_fp {2 * \c_pi_fp} -%^^A } -%^^A {} -% % The wrapping routine might not get it right at the edges so we add in the override. % \begin{macrocode} \array_get:NnNTF \l_hobby_excess_angle_array {##1} \l_tmpa_tl { @@ -997,7 +1013,7 @@ and the derived files hobby.code.tex \array_put:Nnn \l_hobby_matrix_b_array {0} {1} \array_put:Nnn \l_hobby_matrix_c_array {0} {0} \fp_set:Nn \l_hobby_tempa_fp { \l_hobby_out_angle_fp - - \array_get:Nn \l_hobby_angles_array {0} } + - \array_get:Nn \l_hobby_angles_array {0}} % \end{macrocode} % We want to ensure that these angles lie in the range \((-\pi,\pi]\). % So if the angle is bigger than \(\pi\), we subtract \(2 \pi\). @@ -1370,8 +1386,14 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) % The path-generation code doesn't know what to actually do with the path so the initialisation code will set some macros to do that. % This is an auxiliary command that sets these macros. % \begin{macrocode} +\cs_new:Npn \hobby_moveto:nnn #1#2#3 {} +\cs_new:Npn \hobby_curveto:nnn #1#2#3 {} +\cs_new:Npn \hobby_close:n #1 {} +\cs_generate_variant:Nn \hobby_moveto:nnn {VVV,nnV} +\cs_generate_variant:Nn \hobby_curveto:nnn {VVV} +\cs_generate_variant:Nn \hobby_close:n {V} \cs_new:Nn \hobby_set_cmds:nnn { - \cs_gset_eq:NN \hobby_moveto:n #1 + \cs_gset_eq:NN \hobby_moveto:nnn #1 \cs_gset_eq:NN \hobby_curveto:nnn #2 \cs_gset_eq:NN \hobby_close:n #3 } @@ -1498,7 +1520,7 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \cs_new:Nn \hobby_use_path: { \bool_if:NT \l_hobby_disjoint_bool { \array_get:NnN \l_hobby_points_array {0} \l_tmpa_tl - \exp_args:No \hobby_moveto:n {\l_tmpa_tl} + \hobby_moveto:nnV {} {} \l_tmpa_tl } \int_step_inline:nnnn {1} {1} {\l_hobby_npoints_int} { \array_get:NnN \l_hobby_controla_array {##1} \l_tmpa_tl @@ -1506,20 +1528,20 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \array_get:NnN \l_hobby_points_array {##1} \l_tmpc_tl \array_get:NnN \l_hobby_actions_array {##1} \l_tmpd_tl \int_compare:nNnTF {\tl_item:Nn \l_tmpd_tl {1}} = {\l_hobby_draw_int} { - \exp_args:Nooo \hobby_curveto:nnn {\l_tmpa_tl} {\l_tmpb_tl} {\l_tmpc_tl} + \hobby_curveto:VVV \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl }{ \bool_gset_false:N \l_hobby_closed_bool - \exp_args:No \hobby_moveto:n {\l_tmpc_tl} + \hobby_moveto:VVV \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl } \tl_if_eq:xnTF {\tl_item:Nn \l_tmpd_tl {2}} {1} { \bool_gset_false:N \l_hobby_closed_bool - \exp_args:No \hobby_moveto:n {\l_tmpc_tl} + \hobby_moveto:VVV \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl }{} } \bool_if:NT \l_hobby_closed_bool { \array_get:NnN \l_hobby_points_array {0} \l_tmpa_tl - \exp_args:No \hobby_close:n {\l_tmpa_tl} - } + \hobby_close:V \l_tmpa_tl + } } % \end{macrocode} % \end{macro} @@ -1582,6 +1604,8 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \tl_if_exist_p:c {g_hobby_#1_path} && ! \tl_if_exist_p:c {g_hobby_#1_path_saved} + && + \l_hobby_save_aux_bool } { \tl_clear:N \l_tmpa_tl @@ -1673,6 +1697,24 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) } % \end{macrocode} % +% \begin{macro}{hobbyatan2} +% The original PGF version of \Verb+atan2+ had the arguments the wrong way around. +% This was fixed in the CVS version in July 2013, but as old versions are likely to be in use for some time, we define a wrapper function that ensures that the arguments are correct. +% \begin{macrocode} +\pgfmathparse{atan2(0,1)} +\def\hobby@temp{0.0} +\ifx\pgfmathresult\hobby@temp + \pgfmathdeclarefunction{hobbyatan2}{2}{% + \pgfmathatantwo@{#1}{#2}% + } +\else + \pgfmathdeclarefunction{hobbyatan2}{2}{% + \pgfmathatantwo@{#2}{#1}% + } +\fi +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\hobby@curveto} % This is passed to the path-generation code to translate the path into a PGF path. % \begin{macrocode} @@ -1685,8 +1727,8 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) % \begin{macro}{\hobby@moveto} % This is passed to the path-generation code to translate the path into a PGF path. % \begin{macrocode} -\def\hobby@moveto#1{% - \pgfpathmoveto{\hobby@topgf{#1}}% +\def\hobby@moveto#1#2#3{% + \pgfpathmoveto{\hobby@topgf{#3}}% } % \end{macrocode} % \end{macro} @@ -1896,7 +1938,7 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \advance\pgf@xb by -\pgf@xa \advance\pgf@yb by -\pgf@ya \pgfmathsetmacro\hobby@done{sqrt((\pgf@xb/\hobby@sf)^2 + (\pgf@yb/\hobby@sf)^2)}% - \pgfmathsetmacro\hobby@omegaone{rad(atan2(\pgf@xb,\pgf@yb))}% + \pgfmathsetmacro\hobby@omegaone{rad(hobbyatan2(\pgf@yb,\pgf@xb))}% % \end{macrocode} % Now we do the same with the vector from the zeroth to the first point. % \begin{macrocode} @@ -1904,7 +1946,7 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \advance\pgf@xa by -\pgf@x \advance\pgf@ya by -\pgf@y \pgfmathsetmacro\hobby@dzero{sqrt((\pgf@xa/\hobby@sf)^2 + (\pgf@ya/\hobby@sf)^2)}% - \pgfmathsetmacro\hobby@omegazero{rad(atan2(\pgf@xa,\pgf@ya))}% + \pgfmathsetmacro\hobby@omegazero{rad(hobbyatan2(\pgf@ya,\pgf@xa))}% % \end{macrocode} % \Verb+\hobby@psi+ is the angle subtended at the midpoint. % We adjust to ensure that it is in the right range. @@ -2021,7 +2063,6 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) % \end{macrocode} % \end{macro} % -% % \iffalse %</pgflibrary> % \fi @@ -2141,12 +2182,14 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) }, restore Hobby path/.code={% \pgfextra{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \global\let\hobby@collected@onpath\pgfutil@empty \hobbyrestorepath{#1}} }, restore and use Hobby path/.code 2 args={% \pgfextra{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \global\let\hobby@collected@onpath\pgfutil@empty \hobbyrestorepath{#1}% \hobbyusepath{#2}% } @@ -2164,12 +2207,107 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) Hobby externalize/.is if=hobby@externalise } % \end{macrocode} +% +% \begin{macro}{\hobby@tikz@curveto} +% This is passed to the path-generation code to translate the path into a PGF path. +% \begin{macrocode} +\def\hobby@tikz@curveto#1#2#3{% + \pgfutil@ifundefined{tikz@timer@start}{% + \expandafter\hobby@topgf\expandafter{\hobby@initial@pt}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + }{}% + \hobby@topgf{#1}% + \edef\tikz@timer@cont@one{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \hobby@topgf{#2}% + \edef\tikz@timer@cont@two{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \hobby@topgf{#3}% + \let\tikz@timer=\tikz@timer@curve + \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \ifx\hobby@collected@onpath\pgfutil@empty + \else + \expandafter\hobby@nodes@onpath\hobby@collected@onpath\relax\relax + \fi + \pgfpathcurveto{\hobby@topgf{#1}}{\hobby@topgf{#2}}{\hobby@topgf{#3}}% + \hobby@topgf{#3}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\hobby@tikz@moveto} +% This is passed to the path-generation code to translate the path into a PGF path. +% \begin{macrocode} +\def\hobby@tikz@moveto#1#2#3{% + \pgfutil@ifundefined{tikz@timer@start}{% + \expandafter\hobby@topgf\expandafter{\hobby@initial@pt}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + }{}% + \hobby@topgf{#3}% + \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgfutil@empty + \let\tikz@timer=\tikz@timer@line + \else + \hobby@topgf{#1}% + \edef\tikz@timer@cont@one{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \hobby@topgf{#2}% + \edef\tikz@timer@cont@two{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \let\tikz@timer=\tikz@timer@curve + \fi + \ifx\hobby@collected@onpath\pgfutil@empty + \else + \expandafter\hobby@nodes@onpath\hobby@collected@onpath\relax\relax + \fi + \pgfpathmoveto{\hobby@topgf{#3}}% + \hobby@topgf{#3}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\hobby@tikz@close} +% Closes a path. +% \begin{macrocode} +\def\hobby@tikz@close#1{% + \hobby@topgf{#1}% + \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \let\tikz@timer=\tikz@timer@line + \ifx\hobby@collected@onpath\pgfutil@empty + \else + \expandafter\hobby@nodes@onpath\hobby@collected@onpath\relax\relax + \fi + \pgfpathclose +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\hobby@nodes@onpath} +% \begin{macrocode} +\def\hobby@nodes@onpath#1#2\relax{% + \gdef\hobby@collected@onpath{#2}% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgfutil@empty + \else + \def\@gtempa{\relax} + \ifx\pgf@temp\@gtempa + \else + \tikz@node@is@a@labeltrue + \tikz@scan@next@command#1\pgf@stop + \tikz@node@is@a@labelfalse + \fi + \fi +} +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\curvethrough} % This is the parent command. % We initialise the path-generation code, set any parameters, and then hand over control to the point processing macro. % \begin{macrocode} \newcommand\curvethrough[2][]{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \global\let\hobby@collected@onpath\pgfutil@empty + \let\hobby@initial@pt\pgfutil@empty \hobbysetparams{#1}% \tikzset{designated Hobby path=this}% \global\let\hobby@this@opts=\pgfutil@empty @@ -2191,6 +2329,9 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) #1% \pgfmathsetmacro\hobby@x{\the\pgf@x/1cm}% \pgfmathsetmacro\hobby@y{\the\pgf@y/1cm}% + \ifx\hobby@initial@pt\pgfutil@empty + \xdef\hobby@initial@pt{x = \hobby@x, y = \hobby@y}% + \fi \expandafter\hobbyaddpoint\expandafter{\hobby@point@options,% x = \hobby@x, y = \hobby@y}% \def\hobby@point@options{}% @@ -2246,9 +2387,12 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) % To ensure that the generation code is called, we add a lot of hooks to lots of TikZ commands. % \begin{macrocode} \def\hobby@curveto@auto{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \expandafter\gdef\expandafter\hobby@collected@onpath\expandafter{\expandafter{\tikz@collected@onpath} }% + \let\tikz@collected@onpath=\pgfutil@empty \pgfmathsetmacro\hobby@x{\the\tikz@lastx/1cm}% \pgfmathsetmacro\hobby@y{\the\tikz@lasty/1cm}% + \xdef\hobby@initial@pt{x = \hobby@x, y = \hobby@y}% \expandafter\hobbysetparams\expandafter{\hobby@next@opts}% \expandafter\hobbyaddpoint\expandafter{\hobby@point@options,% x = \hobby@x, y = \hobby@y}% @@ -2259,7 +2403,8 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \global\let\hobby@this@opts=\pgfutil@empty \global\let\hobby@next@opts=\pgfutil@empty \global\let\hobby@point@options=\pgfutil@empty - \tikz@scan@one@point\hobby@addfromtikz} + \tikz@scan@one@point\hobby@addfromtikz% +} % \end{macrocode} % \end{macro} % @@ -2349,6 +2494,8 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) % \begin{macro}{\hobby@midcurveto@auto} % \begin{macrocode} \def\hobby@midcurveto@auto{% + \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\hobby@collected@onpath\expandafter\expandafter\expandafter{\expandafter\hobby@collected@onpath\expandafter{\tikz@collected@onpath} }% + \let\tikz@collected@onpath=\pgfutil@empty \let\tikz@scan@point@options=\pgfutil@empty \global\let\hobby@action=\pgfutil@empty \global\let\hobby@this@opts=\pgfutil@empty @@ -2671,6 +2818,7 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \hobby@qinit@tikz@modcmd\tikz@to \hobby@qinit@tikz@modcmd\pgf@stop \hobby@qinit@tikz@modcmd\tikz@decoration + \hobby@qinit@tikz@modcmd\tikz@@close \global\let\hobby@curveto@delegate=\hobby@qmidcurveto@auto } % \end{macrocode} diff --git a/Master/texmf-dist/tex/latex/hobby/hobby.code.tex b/Master/texmf-dist/tex/latex/hobby/hobby.code.tex index 18c3409d5a3..0e567fcc528 100644 --- a/Master/texmf-dist/tex/latex/hobby/hobby.code.tex +++ b/Master/texmf-dist/tex/latex/hobby/hobby.code.tex @@ -20,17 +20,43 @@ \cs_generate_variant:Nn \fp_set:Nn {Nx} \cs_generate_variant:Nn \tl_if_eq:nnTF {VnTF} \cs_generate_variant:Nn \tl_if_eq:nnTF {xnTF} +\tl_clear:N \l_tmpa_tl +\tl_if_exist:NT \g__hobby_version +{ + \tl_set:Nn \l_tmpa_tl { + \ExplSyntaxOff + \tl_clear:N \l_tmpa_tl + \endinput + } +} +\tl_use:N \l_tmpa_tl + +\tl_new:N \g__hobby_version +\tl_new:N \g__hobby_date +\tl_set:Nn \g__hobby_version {1.4} +\tl_set:Nn \g__hobby_date {2014-01-21} +\DeclareDocumentCommand \hobbyVersion {} +{ + \tl_use:N \g__hobby_version +} +\DeclareDocumentCommand \hobbyDate {} +{ + \tl_use:N \g__hobby_date +} \fp_new:N \g_hobby_parama_fp \fp_new:N \g_hobby_paramb_fp \fp_new:N \g_hobby_paramc_fp - \fp_gset:Nn \g_hobby_parama_fp {2^.5} - \fp_gset:Nn \g_hobby_paramb_fp {1/16} - \fp_gset:Nn \g_hobby_paramc_fp {(3-5^.5)/2} \bool_new:N \l_hobby_closed_bool \bool_new:N \l_hobby_disjoint_bool +\bool_new:N \l_hobby_save_aux_bool +\bool_set_true:N \l_hobby_save_aux_bool +\DeclareDocumentCommand \HobbyDisableAux {} +{ + \bool_set_false:N \l_hobby_save_aux_bool +} \array_new:N \l_hobby_points_array \array_new:N \l_hobby_points_x_array \array_new:N \l_hobby_points_y_array @@ -150,16 +176,12 @@ (\array_get:Nn \l_hobby_points_y_array {#1 + 1}) - (\array_get:Nn \l_hobby_points_y_array {#1})} - \fp_atantwo:NNN \l_hobby_tempc_fp \l_hobby_tempb_fp \l_hobby_tempa_fp + \fp_set:Nn \l_hobby_tempc_fp { atan ( \l_hobby_tempb_fp, \l_hobby_tempa_fp ) } \fp_veclen:NVV \l_hobby_tempd_fp \l_hobby_tempa_fp \l_hobby_tempb_fp \array_push:Nx \l_hobby_angles_array {\fp_to_tl:N \l_hobby_tempc_fp} \array_push:Nx \l_hobby_distances_array {\fp_to_tl:N \l_hobby_tempd_fp} } -\cs_new:Nn \fp_atantwo:NNN { - \pgfmathparse{rad(atan2(\fp_use:N #3,\fp_use:N #2))} - \exp_args:NNo \fp_set:Nn #1 {\pgfmathresult} -} \cs_new:Nn \fp_veclen:Nnn { \fp_set:Nn #1 {((#2)^2 + (#3)^2)^.5} } @@ -214,7 +236,7 @@ \fp_if_undefined:NF \l_hobby_out_angle_fp { \fp_set:Nn \l_hobby_tempa_fp { \l_hobby_out_angle_fp - - \array_get:Nn \l_hobby_angles_array {0} } + - \array_get:Nn \l_hobby_angles_array {0}} \fp_compare:nT {\l_hobby_tempa_fp > \c_pi_fp } { \fp_sub:Nn \l_hobby_tempa_fp {2 * \c_pi_fp} @@ -276,7 +298,7 @@ \fp_sub:Nn \l_hobby_tempa_fp {2 * \c_pi_fp} } {} - \fp_compare:nTF {\l_hobby_tempa_fp < -\c_pi_fp } + \fp_compare:nTF {\l_hobby_tempa_fp <= -\c_pi_fp } { \fp_add:Nn \l_hobby_tempa_fp {2 * \c_pi_fp} } @@ -403,7 +425,7 @@ \array_put:Nnn \l_hobby_matrix_b_array {0} {1} \array_put:Nnn \l_hobby_matrix_c_array {0} {0} \fp_set:Nn \l_hobby_tempa_fp { \l_hobby_out_angle_fp - - \array_get:Nn \l_hobby_angles_array {0} } + - \array_get:Nn \l_hobby_angles_array {0}} \fp_compare:nT {\l_hobby_tempa_fp > \c_pi_fp } { \fp_sub:Nn \l_hobby_tempa_fp {2 * \c_pi_fp} @@ -681,8 +703,14 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) #1 } } +\cs_new:Npn \hobby_moveto:nnn #1#2#3 {} +\cs_new:Npn \hobby_curveto:nnn #1#2#3 {} +\cs_new:Npn \hobby_close:n #1 {} +\cs_generate_variant:Nn \hobby_moveto:nnn {VVV,nnV} +\cs_generate_variant:Nn \hobby_curveto:nnn {VVV} +\cs_generate_variant:Nn \hobby_close:n {V} \cs_new:Nn \hobby_set_cmds:nnn { - \cs_gset_eq:NN \hobby_moveto:n #1 + \cs_gset_eq:NN \hobby_moveto:nnn #1 \cs_gset_eq:NN \hobby_curveto:nnn #2 \cs_gset_eq:NN \hobby_close:n #3 } @@ -744,7 +772,7 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \cs_new:Nn \hobby_use_path: { \bool_if:NT \l_hobby_disjoint_bool { \array_get:NnN \l_hobby_points_array {0} \l_tmpa_tl - \exp_args:No \hobby_moveto:n {\l_tmpa_tl} + \hobby_moveto:nnV {} {} \l_tmpa_tl } \int_step_inline:nnnn {1} {1} {\l_hobby_npoints_int} { \array_get:NnN \l_hobby_controla_array {##1} \l_tmpa_tl @@ -752,20 +780,20 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \array_get:NnN \l_hobby_points_array {##1} \l_tmpc_tl \array_get:NnN \l_hobby_actions_array {##1} \l_tmpd_tl \int_compare:nNnTF {\tl_item:Nn \l_tmpd_tl {1}} = {\l_hobby_draw_int} { - \exp_args:Nooo \hobby_curveto:nnn {\l_tmpa_tl} {\l_tmpb_tl} {\l_tmpc_tl} + \hobby_curveto:VVV \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl }{ \bool_gset_false:N \l_hobby_closed_bool - \exp_args:No \hobby_moveto:n {\l_tmpc_tl} + \hobby_moveto:VVV \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl } \tl_if_eq:xnTF {\tl_item:Nn \l_tmpd_tl {2}} {1} { \bool_gset_false:N \l_hobby_closed_bool - \exp_args:No \hobby_moveto:n {\l_tmpc_tl} + \hobby_moveto:VVV \l_tmpa_tl \l_tmpb_tl \l_tmpc_tl }{} } \bool_if:NT \l_hobby_closed_bool { \array_get:NnN \l_hobby_points_array {0} \l_tmpa_tl - \exp_args:No \hobby_close:n {\l_tmpa_tl} - } + \hobby_close:V \l_tmpa_tl + } } \cs_new:Nn \hobby_save_path:n { \tl_clear:N \l_tmpa_tl @@ -817,6 +845,8 @@ sin ( (\array_get:Nn \l_hobby_angles_array {##1}) \tl_if_exist_p:c {g_hobby_#1_path} && ! \tl_if_exist_p:c {g_hobby_#1_path_saved} + && + \l_hobby_save_aux_bool } { \tl_clear:N \l_tmpa_tl diff --git a/Master/texmf-dist/tex/latex/hobby/pgflibraryhobby.code.tex b/Master/texmf-dist/tex/latex/hobby/pgflibraryhobby.code.tex index 5d0f4a91996..37d6a70a6ed 100644 --- a/Master/texmf-dist/tex/latex/hobby/pgflibraryhobby.code.tex +++ b/Master/texmf-dist/tex/latex/hobby/pgflibraryhobby.code.tex @@ -20,11 +20,22 @@ x/.code={\pgf@x=#1cm}, y/.code={\pgf@y=#1cm} } +\pgfmathparse{atan2(0,1)} +\def\hobby@temp{0.0} +\ifx\pgfmathresult\hobby@temp + \pgfmathdeclarefunction{hobbyatan2}{2}{% + \pgfmathatantwo@{#1}{#2}% + } +\else + \pgfmathdeclarefunction{hobbyatan2}{2}{% + \pgfmathatantwo@{#2}{#1}% + } +\fi \def\hobby@curveto#1#2#3{% \pgfpathcurveto{\hobby@topgf{#1}}{\hobby@topgf{#2}}{\hobby@topgf{#3}}% } -\def\hobby@moveto#1{% - \pgfpathmoveto{\hobby@topgf{#1}}% +\def\hobby@moveto#1#2#3{% + \pgfpathmoveto{\hobby@topgf{#3}}% } \def\hobby@topgf#1{% \pgfqkeys{/pgf/hobby}{#1}% @@ -137,12 +148,12 @@ \advance\pgf@xb by -\pgf@xa \advance\pgf@yb by -\pgf@ya \pgfmathsetmacro\hobby@done{sqrt((\pgf@xb/\hobby@sf)^2 + (\pgf@yb/\hobby@sf)^2)}% - \pgfmathsetmacro\hobby@omegaone{rad(atan2(\pgf@xb,\pgf@yb))}% + \pgfmathsetmacro\hobby@omegaone{rad(hobbyatan2(\pgf@yb,\pgf@xb))}% \hobby@qpoints \advance\pgf@xa by -\pgf@x \advance\pgf@ya by -\pgf@y \pgfmathsetmacro\hobby@dzero{sqrt((\pgf@xa/\hobby@sf)^2 + (\pgf@ya/\hobby@sf)^2)}% - \pgfmathsetmacro\hobby@omegazero{rad(atan2(\pgf@xa,\pgf@ya))}% + \pgfmathsetmacro\hobby@omegazero{rad(hobbyatan2(\pgf@ya,\pgf@xa))}% \pgfmathsetmacro\hobby@psi{\hobby@omegaone - \hobby@omegazero}% \pgfmathsetmacro\hobby@psi{\hobby@psi > pi ? \hobby@psi - 2*pi : \hobby@psi}% \pgfmathsetmacro\hobby@psi{\hobby@psi < -pi ? \hobby@psi + 2*pi : \hobby@psi}% diff --git a/Master/texmf-dist/tex/latex/hobby/tikzlibraryhobby.code.tex b/Master/texmf-dist/tex/latex/hobby/tikzlibraryhobby.code.tex index a3fa361d216..ced64271e8b 100644 --- a/Master/texmf-dist/tex/latex/hobby/tikzlibraryhobby.code.tex +++ b/Master/texmf-dist/tex/latex/hobby/tikzlibraryhobby.code.tex @@ -116,12 +116,14 @@ }, restore Hobby path/.code={% \pgfextra{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \global\let\hobby@collected@onpath\pgfutil@empty \hobbyrestorepath{#1}} }, restore and use Hobby path/.code 2 args={% \pgfextra{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \global\let\hobby@collected@onpath\pgfutil@empty \hobbyrestorepath{#1}% \hobbyusepath{#2}% } @@ -138,8 +140,79 @@ Hobby externalise/.is if=hobby@externalise, Hobby externalize/.is if=hobby@externalise } +\def\hobby@tikz@curveto#1#2#3{% + \pgfutil@ifundefined{tikz@timer@start}{% + \expandafter\hobby@topgf\expandafter{\hobby@initial@pt}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + }{}% + \hobby@topgf{#1}% + \edef\tikz@timer@cont@one{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \hobby@topgf{#2}% + \edef\tikz@timer@cont@two{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \hobby@topgf{#3}% + \let\tikz@timer=\tikz@timer@curve + \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \ifx\hobby@collected@onpath\pgfutil@empty + \else + \expandafter\hobby@nodes@onpath\hobby@collected@onpath\relax\relax + \fi + \pgfpathcurveto{\hobby@topgf{#1}}{\hobby@topgf{#2}}{\hobby@topgf{#3}}% + \hobby@topgf{#3}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% +} +\def\hobby@tikz@moveto#1#2#3{% + \pgfutil@ifundefined{tikz@timer@start}{% + \expandafter\hobby@topgf\expandafter{\hobby@initial@pt}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + }{}% + \hobby@topgf{#3}% + \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgfutil@empty + \let\tikz@timer=\tikz@timer@line + \else + \hobby@topgf{#1}% + \edef\tikz@timer@cont@one{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \hobby@topgf{#2}% + \edef\tikz@timer@cont@two{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \let\tikz@timer=\tikz@timer@curve + \fi + \ifx\hobby@collected@onpath\pgfutil@empty + \else + \expandafter\hobby@nodes@onpath\hobby@collected@onpath\relax\relax + \fi + \pgfpathmoveto{\hobby@topgf{#3}}% + \hobby@topgf{#3}% + \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% +} +\def\hobby@tikz@close#1{% + \hobby@topgf{#1}% + \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \let\tikz@timer=\tikz@timer@line + \ifx\hobby@collected@onpath\pgfutil@empty + \else + \expandafter\hobby@nodes@onpath\hobby@collected@onpath\relax\relax + \fi + \pgfpathclose +} +\def\hobby@nodes@onpath#1#2\relax{% + \gdef\hobby@collected@onpath{#2}% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgfutil@empty + \else + \def\@gtempa{\relax} + \ifx\pgf@temp\@gtempa + \else + \tikz@node@is@a@labeltrue + \tikz@scan@next@command#1\pgf@stop + \tikz@node@is@a@labelfalse + \fi + \fi +} \newcommand\curvethrough[2][]{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \global\let\hobby@collected@onpath\pgfutil@empty + \let\hobby@initial@pt\pgfutil@empty \hobbysetparams{#1}% \tikzset{designated Hobby path=this}% \global\let\hobby@this@opts=\pgfutil@empty @@ -152,6 +225,9 @@ #1% \pgfmathsetmacro\hobby@x{\the\pgf@x/1cm}% \pgfmathsetmacro\hobby@y{\the\pgf@y/1cm}% + \ifx\hobby@initial@pt\pgfutil@empty + \xdef\hobby@initial@pt{x = \hobby@x, y = \hobby@y}% + \fi \expandafter\hobbyaddpoint\expandafter{\hobby@point@options,% x = \hobby@x, y = \hobby@y}% \def\hobby@point@options{}% @@ -183,9 +259,12 @@ \def\hobby@curveto@override{% \hobby@curveto@delegate} \def\hobby@curveto@auto{% - \hobbyinit\hobby@moveto\hobby@curveto\hobby@close + \hobbyinit\hobby@tikz@moveto\hobby@tikz@curveto\hobby@tikz@close + \expandafter\gdef\expandafter\hobby@collected@onpath\expandafter{\expandafter{\tikz@collected@onpath} }% + \let\tikz@collected@onpath=\pgfutil@empty \pgfmathsetmacro\hobby@x{\the\tikz@lastx/1cm}% \pgfmathsetmacro\hobby@y{\the\tikz@lasty/1cm}% + \xdef\hobby@initial@pt{x = \hobby@x, y = \hobby@y}% \expandafter\hobbysetparams\expandafter{\hobby@next@opts}% \expandafter\hobbyaddpoint\expandafter{\hobby@point@options,% x = \hobby@x, y = \hobby@y}% @@ -196,7 +275,8 @@ \global\let\hobby@this@opts=\pgfutil@empty \global\let\hobby@next@opts=\pgfutil@empty \global\let\hobby@point@options=\pgfutil@empty - \tikz@scan@one@point\hobby@addfromtikz} + \tikz@scan@one@point\hobby@addfromtikz% +} \def\hobby@addfromtikz#1{% #1% \tikz@make@last@position{#1}% @@ -255,6 +335,8 @@ \expandafter\global\expandafter\let\expandafter#1\csname hobby@orig@\string#1\endcsname% } \def\hobby@midcurveto@auto{% + \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\hobby@collected@onpath\expandafter\expandafter\expandafter{\expandafter\hobby@collected@onpath\expandafter{\tikz@collected@onpath} }% + \let\tikz@collected@onpath=\pgfutil@empty \let\tikz@scan@point@options=\pgfutil@empty \global\let\hobby@action=\pgfutil@empty \global\let\hobby@this@opts=\pgfutil@empty @@ -467,6 +549,7 @@ \hobby@qinit@tikz@modcmd\tikz@to \hobby@qinit@tikz@modcmd\pgf@stop \hobby@qinit@tikz@modcmd\tikz@decoration + \hobby@qinit@tikz@modcmd\tikz@@close \global\let\hobby@curveto@delegate=\hobby@qmidcurveto@auto } \def\hobby@qrestore@tikz@commands{% |