summaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-07-23 03:01:14 +0000
committerNorbert Preining <norbert@preining.info>2023-07-23 03:01:14 +0000
commit8e64fc98a1773bc22a0f010f106d56a028e48597 (patch)
tree29781e66044aca74e0a9fe7b15b9bedde97e5892 /graphics
parent05bb4f9ed131a04f54560a856dfbd7bc15981555 (diff)
CTAN sync 202307230301
Diffstat (limited to 'graphics')
-rw-r--r--graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.pdfbin862646 -> 1000703 bytes
-rw-r--r--graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.tex109
-rw-r--r--graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.pdfbin867272 -> 1005336 bytes
-rw-r--r--graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.tex103
-rw-r--r--graphics/metapost/contrib/macros/mpchess/doc/mpchess-preamble.tex2
-rw-r--r--graphics/metapost/contrib/macros/mpchess/fonts/mpchessfont.ttfbin38292 -> 38292 bytes
-rw-r--r--graphics/metapost/contrib/macros/mpchess/metapost/mpchess-pieces.mp18
-rw-r--r--graphics/metapost/contrib/macros/mpchess/metapost/mpchess.mp82
-rw-r--r--graphics/pgf/contrib/tikz-nfold/README.md2
-rw-r--r--graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex170
-rw-r--r--graphics/pgf/contrib/tikz-nfold/pgflibrarynfold.code.tex88
-rw-r--r--graphics/pgf/contrib/tikz-nfold/pgflibraryoffsetpath.code.tex913
-rw-r--r--graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.pdfbin302816 -> 304060 bytes
-rw-r--r--graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.tex38
-rw-r--r--graphics/pgf/contrib/tikz-nfold/tikzlibrarynfold.code.tex1303
-rw-r--r--graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.pdfbin604526 -> 605728 bytes
-rw-r--r--graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.tex33
-rw-r--r--graphics/pgf/contrib/tikz3d-fr/tex/tikz3d-fr.sty27
18 files changed, 1354 insertions, 1534 deletions
diff --git a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.pdf b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.pdf
index 421fa6b060..741544029e 100644
--- a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.pdf
+++ b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.pdf
Binary files differ
diff --git a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.tex b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.tex
index bcc74e5003..5ad5abdb1a 100644
--- a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.tex
+++ b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-en.tex
@@ -68,7 +68,7 @@
}
\vfill
\begin{center}
- Version 0.6, 2023, April, 26th \\
+ Version 0.7, 2023, July, 20th \\
\url{https://plmlab.math.cnrs.fr/mchupin/mpchess}
\end{center}
%% == Page de garde ====================================================
@@ -293,12 +293,15 @@ command:
\item[\meta{string}] can be:
\begin{itemize}
\item \lstinline+"BlueLichess"+ (default);
-\item \lstinline+"BrownLichess"+ ;
+\item \lstinline+"BrownLichess"+;
+\item \lstinline+"GreenLichess"+;
+\item \lstinline+"PinkPyramidalLichess"+;
+\item \lstinline+"Wood"+;
\item or \lstinline+"Classical"+.
\end{itemize}
\end{description}
-The following examples show the results obtained from each theme:
+The following example shows the results obtained from \lstinline+"BrownLichess"+:
\begin{ExempleMP}
input mpchess
beginfig(0);
@@ -307,21 +310,65 @@ init_backboard;
draw backboard;
endfig;
\end{ExempleMP}
-\begin{ExempleMP}
-input mpchess
-beginfig(0);
-set_color_theme("Classical");
-init_backboard;
-draw backboard;
-endfig;
-\end{ExempleMP}
-The two color themes provided borrow the colors of the Lichess themes.
+The table~\ref{tab:color} shows the different results of the different themes.
+
+\begin{table}
+ \centering
+\begin{tabular}{cc}
+
+\lstinline+"GreenLichess"+ theme&\lstinline+"Classical"+ theme\\
+\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("GreenLichess");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}
+&\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("Classical");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}\\
+\lstinline+"PinkPyramidalLichess"+ theme& \lstinline+"Wood"+ theme\\
+\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("PinkPyramidalLichess");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}&
+\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("Wood");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}\\
+\end{tabular}
+\caption{The different color themes provided by \mpchess.}\label{tab:color}
+\end{table}
+
\subsubsection{Configuring a Personal Color Theme}
-A color theme is really just the definition of two colors.
+\paragraph{Colors.}
+A color theme is the definition of two colors.
These can be defined with the following commands\footnote{Attention,
in version 0.6, \lstinline+set_white_color+ became
\lstinline+set_white_squares_color+ and \lstinline+set_black_color+ became
@@ -341,6 +388,40 @@ init_backboard;
draw backboard;
endfig;
\end{ExempleMP}
+
+\paragraph{Color Types.}
+
+To choose a type, you can use the following command:
+
+\commande|set_board_type(«string»)|\index{set_board_type@\lstinline+set_board_type+}\smallskip
+
+
+Three types of coloring are available:
+
+\begin{description}
+ \item[\meta{string}] can be:
+\begin{itemize}
+\item \lstinline+"flat"+, simple flat coloring (default);
+\item \lstinline+"pyramidal"+, Lichess \emph{pyramidal} coloring;
+\item \lstinline+"wood"+, wood imitation.
+\end{itemize}
+\end{description}
+
+Here is an example coupling color and type definitions.
+
+\begin{ExempleMP}
+input mpchess
+beginfig(0);
+set_white_squares_color((0.9,0.8,0.8));
+set_black_squares_color((0.7,0.6,0.6));
+set_board_type("wood");
+init_backboard;
+draw backboard;
+endfig;
+\end{ExempleMP}
+
+
+
\subsection{Display Coordinates}
You may have noticed in the various examples that by default, the coordinates are, as on the Lichess site, written in small letters inside the boxes.
@@ -1367,6 +1448,8 @@ endfig;
\section{History}
\begin{description}
+\item[v0.7, juillet 2023:] Black knight adjustment, adding color board themes (\lstinline+GreenLichess+, \lstinline+PinkPyramidalLichess+,
+\lstinline+Wood+ with color type (\lstinline+set_board_type+).
\item[v0.6, April 26, 2023:] Fixed bugs concerning castling management, and
moves ambiguities in \textsc{pgn} format.
Changed \lstinline+set_white_color+ to
diff --git a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.pdf b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.pdf
index fd467b6595..bcca5a85f9 100644
--- a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.pdf
+++ b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.pdf
Binary files differ
diff --git a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.tex b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.tex
index 2ee8714da4..db6a5f8b86 100644
--- a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.tex
+++ b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-doc-fr.tex
@@ -71,7 +71,7 @@
}
\vfill
\begin{center}
- Version 0.6, 26 avril 2023 \\
+ Version 0.7, 20 juillet 2023 \\
\url{https://plmlab.math.cnrs.fr/mchupin/mpchess}
\end{center}
%% == Page de garde ====================================================
@@ -289,6 +289,9 @@ Plusieurs thèmes de couleurs sont accessibles. Pour choisir un thème de couleu
\begin{itemize}
\item \lstinline+"BlueLichess"+ (thème par défaut);
\item \lstinline+"BrownLichess"+ ;
+\item \lstinline+"GreenLichess"+;
+\item \lstinline+"PinkPyramidalLichess"+;
+\item \lstinline+"Wood"+;
\item ou \lstinline+"Classical"+.
\end{itemize}
\end{description}
@@ -302,20 +305,64 @@ init_backboard;
draw backboard;
endfig;
\end{ExempleMP}
-\begin{ExempleMP}
-input mpchess
-beginfig(0);
-set_color_theme("Classical");
-init_backboard;
-draw backboard;
-endfig;
-\end{ExempleMP}
-Les deux thèmes colorés fournis empruntent les couleurs des thèmes de Lichess.
+Le tableau~\ref{tab:color} montre les résultats des différents thèmes fournis
+par \mpchess.
+
+\begin{table}
+ \centering
+\begin{tabular}{cc}
+
+Thème \lstinline+"GreenLichess"+&Thème \lstinline+"Classical"+\\
+\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("GreenLichess");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}
+&\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("Classical");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}\\
+Thème \lstinline+"PinkPyramidalLichess"+&Thème \lstinline+"Wood"+\\
+\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("PinkPyramidalLichess");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}&
+\begin{mplibcode}
+ input mpchess
+ beginfig(0);
+ init_chessboard;
+ set_backboard_width(4cm);
+ set_color_theme("Wood");
+ init_backboard;
+ draw backboard;
+ endfig;
+\end{mplibcode}\\
+\end{tabular}
+\caption{Les différents thèmes de couleur fournis par \mpchess.}\label{tab:color}
+\end{table}
\subsubsection{Configuration d’un thème personnel}
-Un thème de couleur est en réalité simplement la définition de deux couleurs.
+\paragraph{Couleurs.}
+Un thème de couleur conciste en la définition de deux couleurs.
Celles-ci peuvent se définir avec les commandes suivantes \footnote{Attention,
lors du passage à la version 0.6, \lstinline+set_white_color+ est devenu
\lstinline+set_white_squares_color+ et \lstinline+set_black_color+ est devenu
@@ -335,6 +382,37 @@ init_backboard;
draw backboard;
endfig;
\end{ExempleMP}
+
+\paragraph{Type de coloriage.}
+
+
+On peut choisir un type de coloriage avec la commande suivante:
+
+\commande|set_board_type(«string»)|\index{set_board_type@\lstinline+set_board_type+}\smallskip
+
+Les trois types de coloriage fournis par \mpchess{} se choisissent avec
+\begin{description}
+ \item[\meta{string}] qui peut valoir:
+\begin{itemize}
+\item \lstinline+"flat"+, coloriage à plat (défaut);
+\item \lstinline+"pyramidal"+, coloriage \emph{pyramidal} à la Lichess;
+\item \lstinline+"wood"+, imitation bois.
+\end{itemize}
+\end{description}
+
+Voici un exemple de paramétrage de couleur et de type de coloriage.
+
+\begin{ExempleMP}
+input mpchess
+beginfig(0);
+set_white_squares_color((0.9,0.8,0.8));
+set_black_squares_color((0.7,0.6,0.6));
+set_board_type("wood");
+init_backboard;
+draw backboard;
+endfig;
+\end{ExempleMP}
+
\subsection{Affichage des coordonnées}
Vous avez pu constater dans les divers exemples que par défaut, les coordonnées
@@ -1346,6 +1424,9 @@ endfig;
\section{Historique}
\begin{description}
+\item[v0.7, juillet 2023:] Ajustement du cavalier noir, ajout de thèmes
+d'échiquier (\lstinline+GreenLichess+, \lstinline+PinkPyramidalLichess+,
+\lstinline+Wood+ avec des types de coloriage (\lstinline+set_board_type+).
\item[v0.6, avril 2023:] Corrections de bugs concernant la gestion des roques, et
des ambiguïtés de pièces pour les déplacements sous format \textsc{pgn}.
Changement de \lstinline+set_white_color+ en
diff --git a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-preamble.tex b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-preamble.tex
index 62e5ad2413..6a7f11d747 100644
--- a/graphics/metapost/contrib/macros/mpchess/doc/mpchess-preamble.tex
+++ b/graphics/metapost/contrib/macros/mpchess/doc/mpchess-preamble.tex
@@ -97,7 +97,7 @@
set_no_coords,set_white_view,set_black_view,
set_white_player,set_black_player,set_pieces_theme,set_players_side,init_chessboard,set_empty_chessboard,add_white_pieces,add_black_pieces,clear_areas,clear_files,clear_ranks,clear_squares,build_chessboard_from_fen,build_chessboards_from_pgn,clear_chessboard,
color_square,draw_arrows,draw_circles,draw_comment,draw_crosses,get_halfmove_number,get_totalmove_number,
- reset_mpchess,set_black_to_move,set_last_move_color,set_comment_color,set_white_to_move,set_whos_to_move,show_last_move,unset_whos_to_move,set_arrow_width,clip_chessboard,build_chessboard_from_fen_file,build_chessboard_from_pgn_file,draw_black_main_lines,draw_black_main_lines_step,draw_white_main_lines,draw_white_main_lines_step,set_main_lines_color,set_possible_moves_color,show_possible_moves,show_possible_moves_step,hide_coordinates,hide_whos_to_move,set_black_squares_color,set_coordinates_font,set_coordinates_position,set_white_squares_color,show_coordinates,show_whos_to_move},
+ reset_mpchess,set_black_to_move,set_last_move_color,set_comment_color,set_white_to_move,set_whos_to_move,show_last_move,unset_whos_to_move,set_arrow_width,clip_chessboard,build_chessboard_from_fen_file,build_chessboard_from_pgn_file,draw_black_main_lines,draw_black_main_lines_step,draw_white_main_lines,draw_white_main_lines_step,set_main_lines_color,set_possible_moves_color,show_possible_moves,show_possible_moves_step,hide_coordinates,hide_whos_to_move,set_black_squares_color,set_coordinates_font,set_coordinates_position,set_white_squares_color,show_coordinates,show_whos_to_move,set_board_type},
keywordstyle=\color{darkred},
classoffset=2,% frame=tb
morekeywords={backboard,chessboard,chessboard_step},
diff --git a/graphics/metapost/contrib/macros/mpchess/fonts/mpchessfont.ttf b/graphics/metapost/contrib/macros/mpchess/fonts/mpchessfont.ttf
index 11f0bef692..000d741430 100644
--- a/graphics/metapost/contrib/macros/mpchess/fonts/mpchessfont.ttf
+++ b/graphics/metapost/contrib/macros/mpchess/fonts/mpchessfont.ttf
Binary files differ
diff --git a/graphics/metapost/contrib/macros/mpchess/metapost/mpchess-pieces.mp b/graphics/metapost/contrib/macros/mpchess/metapost/mpchess-pieces.mp
index 0d6aa5ea24..7a5de31b95 100644
--- a/graphics/metapost/contrib/macros/mpchess/metapost/mpchess-pieces.mp
+++ b/graphics/metapost/contrib/macros/mpchess/metapost/mpchess-pieces.mp
@@ -51,14 +51,14 @@ linejoin := mitered;
fill (19.250000,7.917970)..controls (22.527300,7.917970) and (22.671900,5.488280)..(22.671900,3.679690)
--(5.632810,3.679690)..controls (5.632810,5.519530) and (5.777340,7.917970)..(9.054690,7.917970)
--cycle;
-fill (19.257799,9.101560)--(9.082030,9.101560)..controls (9.218750,12.449200) and (13.515600,14.226600)..(13.710900,15.843800)
- ..controls (13.906300,17.457001) and (13.031300,17.875000)..(13.031300,17.875000)
- ..controls (13.031300,17.875000) and (12.433600,15.933600)..(11.668000,15.535200)
- ..controls (10.902300,15.136700) and (9.125000,14.765600)..(9.125000,14.765600)
- ..controls (9.125000,14.765600) and (7.875000,13.789100)..(7.140630,13.855500)
- ..controls (6.406250,13.925800) and (5.773440,15.449200)..(5.773440,15.449200)
- --(8.273440,18.898399)--(9.539060,21.347700)--(10.734400,22.476601)
- --(11.246100,24.136700)--(12.683600,22.675800)..controls (20.597700,22.675800) and (22.316401,13.824200)..(19.257799,9.101560)
+fill (18.890600,9.101560)--(9.410160,9.101560)..controls (9.539060,12.566400) and (13.539100,14.410200)..(13.722700,16.085899)
+ ..controls (13.906300,17.757799) and (13.089800,18.187500)..(13.089800,18.187500)
+ ..controls (13.089800,18.187500) and (12.531300,16.175800)..(11.820300,15.765600)
+ ..controls (11.109400,15.355500) and (9.449220,14.968800)..(9.449220,14.968800)
+ ..controls (9.449220,14.968800) and (8.289060,13.957000)..(7.601560,14.027300)
+ ..controls (6.917970,14.097700) and (6.332030,15.675800)..(6.332030,15.675800)
+ --(8.656250,19.253901)--(9.835940,21.785200)--(10.949200,22.957001)
+ --(11.425800,24.675800)--(12.765600,23.164101)..controls (20.140600,23.164101) and (21.738300,13.992200)..(18.890600,9.101560)
--cycle;
);
@@ -363,4 +363,4 @@ draw (19.609400,21.625000)--(17.171900,22.253901)--(16.644501,21.011700)
--(8.683590,21.382799)..controls (8.683590,21.382799) and (8.660160,17.046900)..(9.914060,17.070299)
--(18.378901,17.070299)..controls (19.628901,17.070299) and (19.609400,21.625000)..(19.609400,21.625000)
--cycle;
-); \ No newline at end of file
+);
diff --git a/graphics/metapost/contrib/macros/mpchess/metapost/mpchess.mp b/graphics/metapost/contrib/macros/mpchess/metapost/mpchess.mp
index d16c821493..3883ca0bc3 100644
--- a/graphics/metapost/contrib/macros/mpchess/metapost/mpchess.mp
+++ b/graphics/metapost/contrib/macros/mpchess/metapost/mpchess.mp
@@ -1,8 +1,8 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% mpchess.mp %%
%% draw chessboards with metapost %%
-%% chupin@ceremade.dauphine.fr %%
-%% Version 0.6 (avril 2023) %%
+%% notezik@gmail.com %%
+%% Version 0.7 (juillet 2023) %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This work may be distributed and/or modified under the conditions of
@@ -21,6 +21,7 @@ input mpchess-skak; % piece of skak package
input mpchess-chessboard;
input mpchess-pgn;
input mpchess-fen;
+input fiziko;
if not known mplib: input latexmp fi;
@@ -198,13 +199,54 @@ picture _blackSquarePic, _whiteSquarePic;
picture _blackSquareColoredPic, _whiteSquareColoredPic;
picture _blackSquareClassicalPic, _whiteSquareClassicalPic;
+def _wood_draw(expr N,d,p,c,_SquareUnit)=
+ save _up_wood,_down_wood;
+ path _up_wood,_down_wood;
+ fill unitsquare scaled _SquareUnit withcolor c;
+ for i=1 upto N-1:
+ _up_wood:=(i/N+uniformdeviate(d),0.0+0.5p/_SquareUnit)*_SquareUnit--(i/N,0.0+0.5p/_SquareUnit)*_SquareUnit--(i/N,0.5)*_SquareUnit--(i/N+uniformdeviate(d),0.7+uniformdeviate(.3)-p/_SquareUnit)*_SquareUnit--cycle;
+ fill _up_wood withcolor ((0.9+uniformdeviate
+ .25)[white,c]);
+ _down_wood:=((i-1)/N+uniformdeviate(d)+0.5/N,1.0-0.5p/_SquareUnit)*_SquareUnit--((i-1)/N+0.5/N,1.0-0.5p/_SquareUnit)*_SquareUnit--((i-1)/N+0.5/N,0.5)*_SquareUnit--((i-1)/N+uniformdeviate(d)+0.5/N,0.3-uniformdeviate(.3)+p/_SquareUnit)*_SquareUnit--cycle;
+ fill _down_wood withcolor ((0.9+uniformdeviate
+ .25)[white,c]);
+ endfor;
+enddef;
+
def _buildColoredSquare(expr _SquareUnit,_BlackColor,_WhiteColor)=
- _blackSquarePic:=image(
- fill unitsquare scaled _SquareUnit withcolor _BlackColor;
- );
- _whiteSquarePic:=image(
- fill unitsquare scaled _SquareUnit withcolor _WhiteColor;
- );
+ if(_chess_board_type="flat"):
+ _blackSquarePic:=image(
+ fill unitsquare scaled _SquareUnit withcolor _BlackColor;
+ );
+ _whiteSquarePic:=image(
+ fill unitsquare scaled _SquareUnit withcolor _WhiteColor;
+ );
+ elseif(_chess_board_type="pyramidal"):
+ _blackSquarePic:=image(
+ fill unitsquare scaled _SquareUnit withcolor _BlackColor;
+ fill (1,0)--(1,1)--(0.5,0.5)--cycle scaled _SquareUnit withcolor
+ 0.97[black,_BlackColor];
+ fill (0,1)--(0,0)--(0.5,0.5)--cycle scaled _SquareUnit withcolor
+ 0.97[white,_BlackColor];
+ );
+ _whiteSquarePic:=image(
+ fill unitsquare scaled _SquareUnit withcolor _WhiteColor;
+ fill (1,0)--(1,1)--(0.5,0.5)--cycle scaled _SquareUnit withcolor
+ 0.97[black,_WhiteColor];
+ fill (0,1)--(0,0)--(0.5,0.5)--cycle scaled _SquareUnit withcolor
+ 0.97[white,_WhiteColor];
+ );
+ elseif(_chess_board_type="wood"):
+ _N_wood:=20;
+ _deviate_wood:=0.02;
+ _pencile_wood:=0.7pt;
+ path _up_wood,_down_wood,_q,_p;
+ _blackSquarePic:=image(
+ _wood_draw(_N_wood,_deviate_wood,_pencile_wood,_BlackColor,_SquareUnit);
+ );
+ _whiteSquarePic:=image(_wood_draw(_N_wood,_deviate_wood,_pencile_wood,_WhiteColor,_SquareUnit);
+ );
+ fi
enddef;
def _buildClassicalSquare(expr _SquareUnit)=
@@ -223,11 +265,25 @@ _whiteSquarePic:=_whiteSquareColoredPic;
def set_color_theme(expr t)=
_chessTheme := t;
if(t="BlueLichess"):
+ _chess_board_type:="flat";
_blackColorSquare:=(0.549,0.6353,0.6784);
_whiteColorSquare:=(0.8706,0.8912,0.902);
elseif(t="BrownLichess"):
+ _chess_board_type:="flat";
_blackColorSquare:=(0.709803922,0.5333,0.3882);
_whiteColorSquare:=(0.941176471,0.850980392,0.709803922);
+ elseif(t="GreenLichess"):
+ _chess_board_type:="flat";
+ _blackColorSquare:=(0.5255,0.651,0.4);
+ _whiteColorSquare:=(1.0,1.0,0.8666);
+ elseif(t="PinkPyramidalLichess"):
+ _chess_board_type:="pyramidal";
+ _blackColorSquare:=(0.949,0.451,0.451);
+ _whiteColorSquare:=(0.9294,0.9333,0.73333);
+ elseif(t="Wood"):
+ _chess_board_type:="wood";
+ _blackColorSquare:=(0.4902,0.3569,0.2118);
+ _whiteColorSquare:=(0.8039,0.7843,0.7725);
elseif(t="Classical"):
_blackColorSquare:=black;
_whiteColorSquare:=black;
@@ -490,6 +546,16 @@ enddef;
picture backboard;
+string _chess_board_type; % define flat color or "pyramidal" like lichess
+
+% default value flat
+_chess_board_type:="flat";
+
+vardef set_board_type(expr s) =
+ _chess_board_type:=s;
+enddef;
+
+
def init_backboard =
_chessSquareU:=_chessWidth/_chessSize;
_init_piece(_chessSquareU);
diff --git a/graphics/pgf/contrib/tikz-nfold/README.md b/graphics/pgf/contrib/tikz-nfold/README.md
index c146668713..4c1d75c249 100644
--- a/graphics/pgf/contrib/tikz-nfold/README.md
+++ b/graphics/pgf/contrib/tikz-nfold/README.md
@@ -1,5 +1,5 @@
# tikz-nfold
-## Version 0.1.3
+## Version 1.0.0
This library adds higher-order paths to [TikZ](https://ctan.org/pkg/pgf) and also fixes some graphical issues with TikZ' `double` paths, used e.g. in wide arrows. It is also compatible with [tikz-cd](https://ctan.org/pkg/tikz-cd), adding support for triple and higher arrows. See the [documentation](tikz-nfold-doc.pdf) for full details.
diff --git a/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex b/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
index 275fa0fdf3..06c9912f6c 100644
--- a/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
+++ b/graphics/pgf/contrib/tikz-nfold/pgflibrarybezieroffset.code.tex
@@ -1,4 +1,4 @@
-%% tikz-nfold.sty
+%% pgflibrarybezieroffset.code.tex
%% Copyright 2023 Jonathan Schulz
%
% This work may be distributed and/or modified under the
@@ -13,102 +13,40 @@
%
% The Current Maintainer of this work is Jonathan Schulz.
%
-% This work consists of the files pgflibrarybezieroffset.code.tex,
-% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+% This work consists of the files
+% pgflibrarybezieroffset.code.tex, pgflibrarynfold.code.tex, pgflibraryoffsetpath.code.tex, tikz-nfold-doc.tex, tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+%
+%
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
+%
-% Don't delete this code in case we need it in the future
-%
-% Split a Bezier curve (de Casteljau's algorithm)
-% #1 = time (between 0 and 1)
-% #2-#5: control points
-% Outputs the first part into \pgf@splitbezier@i@i, ... , \pgf@splitbezier@i@iv,
-% and the second part into \pgf@splitbezier@ii@i, ... , \pgf@splitbezier@ii@iv.
-%\def\pgf@splitbezier#1#2#3#4#5{%
-% % based on pgfcorepoints.code.tex, \pgfpointcurveattime
-% \edef\pgf@time@s{#1}%
-% \pgf@x=-\pgf@time@s pt%
-% \advance\pgf@x by 1pt%
-% \edef\pgf@time@t{\pgf@sys@tonumber{\pgf@x}}%
-% % P^0_3
-% \pgfextract@process\pgf@splitbezier@ii@iv{#5}%
-% \pgf@xc=\pgf@x%
-% \pgf@yc=\pgf@y%
-% % P^0_2
-% \pgf@process{#4}%
-% \pgf@xb=\pgf@x%
-% \pgf@yb=\pgf@y%
-% % P^0_1
-% \pgf@process{#3}%
-% \pgf@xa=\pgf@x%
-% \pgf@ya=\pgf@y%
-% % P^0_0
-% \pgfextract@process\pgf@splitbezier@i@i{#2}%
-% % First iteration:
-% % P^1_0
-% \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
-% \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
-% \pgfextract@process\pgf@splitbezier@i@ii{}%
-% % P^1_1
-% \pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb%
-% \pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb%
-% % P^1_2
-% \pgf@xb=\pgf@time@t\pgf@xb\advance\pgf@xb by\pgf@time@s\pgf@xc%
-% \pgf@yb=\pgf@time@t\pgf@yb\advance\pgf@yb by\pgf@time@s\pgf@yc%
-% \edef\pgf@splitbezier@ii@iii{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
-% % P^2_0
-% \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
-% \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
-% \pgfextract@process\pgf@splitbezier@i@iii{}%
-% % P^2_1
-% \pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb%
-% \pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb%
-% \edef\pgf@splitbezier@ii@ii{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
-% % P^3_0
-% \pgf@x=\pgf@time@t\pgf@x\advance\pgf@x by\pgf@time@s\pgf@xa%
-% \pgf@y=\pgf@time@t\pgf@y\advance\pgf@y by\pgf@time@s\pgf@ya%
-% \pgfextract@process\pgf@splitbezier@i@iv{}%
-% \let\pgf@splitbezier@ii@i\pgf@splitbezier@i@iv
-%}
-% Split the Bezier curve defined by #1-#4 at t=0.5 using de Casteljau's algorithm
\def\pgf@halfsplitbezier#1#2#3#4{%
- % based on pgfcorepoints.code.tex, \pgfpointcurveattime
- % P^0_3
\pgfextract@process\pgf@splitbezier@ii@iv{#4}%
\pgf@xc=\pgf@x%
\pgf@yc=\pgf@y%
- % P^0_2
- \pgf@process{#3}% removing these does not yield a significant speedup
+ \pgf@process{#3}%
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
- % P^0_1
\pgf@process{#2}%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
- % P^0_0
\pgfextract@process\pgf@splitbezier@i@i{#1}%
- % First iteration:
- % P^1_0
\pgf@x=.5\pgf@x\advance\pgf@x by.5\pgf@xa%
\pgf@y=.5\pgf@y\advance\pgf@y by.5\pgf@ya%
\edef\pgf@splitbezier@i@ii{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}%
- % P^1_1
\pgf@xa=.5\pgf@xa\advance\pgf@xa by.5\pgf@xb%
\pgf@ya=.5\pgf@ya\advance\pgf@ya by.5\pgf@yb%
- % P^1_2
\pgf@xb=.5\pgf@xb\advance\pgf@xb by.5\pgf@xc%
\pgf@yb=.5\pgf@yb\advance\pgf@yb by.5\pgf@yc%
\edef\pgf@splitbezier@ii@iii{\pgf@x\the\pgf@xb\pgf@y\the\pgf@yb}%
- % P^2_0
\pgf@x=.5\pgf@x\advance\pgf@x by.5\pgf@xa%
\pgf@y=.5\pgf@y\advance\pgf@y by.5\pgf@ya%
\edef\pgf@splitbezier@i@iii{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}%
- % P^2_1
\pgf@xa=.5\pgf@xa\advance\pgf@xa by.5\pgf@xb%
\pgf@ya=.5\pgf@ya\advance\pgf@ya by.5\pgf@yb%
\edef\pgf@splitbezier@ii@ii{\pgf@x\the\pgf@xa\pgf@y\the\pgf@ya}%
- % P^3_0
\pgf@x=.5\pgf@x\advance\pgf@x by.5\pgf@xa%
\pgf@y=.5\pgf@y\advance\pgf@y by.5\pgf@ya%
\edef\pgf@splitbezier@i@iv{\pgf@x\the\pgf@x\pgf@y\the\pgf@y}%
@@ -116,7 +54,6 @@
}
-% computes the cross product and puts it into \pgfmathresult
\def\pgfmathcrossproduct#1#2{%
\begingroup
\pgf@process{#1}%
@@ -159,7 +96,6 @@
\endgroup\pgf@temp
}
-% Calculates abs(\pgf@x) + abs(\pgf@y) in #1
\def\pgfpointtaxicabnorm#1{%
\ifdim\pgf@x<0pt
#1=-\pgf@x
@@ -173,24 +109,18 @@
\fi
}
-% Computes the normalised tangents of a given Bezier curve and stores them in \pgf@tmp@tang@i and \pgf@tmp@tang@ii.
-% Also computes the angles and stores them in \pgf@tmp@angle@i and \pgf@tmp@angle@ii.
-% All degenerate cases are covered. For a triple degenerate curve (all points equal), the vector (1,0) is returned.
\def\pgf@offset@compute@tangents#1#2#3#4{%
- \pgf@process{\pgfpointdiff{#1}{#2}}% unintuitively, this is PTii - PTi
+ \pgf@process{\pgfpointdiff{#1}{#2}}%
\pgfpointtaxicabnorm\pgf@xa
\ifdim\pgf@xa<0.1pt\relax
- % edge case: first point and first control point are equal
\pgf@process{\pgfpointdiff{#1}{#3}}%
\pgfpointtaxicabnorm\pgf@xa
\ifdim\pgf@xa<0.1pt\relax
- % edge case: first three points are equal
\pgf@process{\pgfpointdiff{#1}{#4}}%
\fi
\fi
\pgfextract@process\pgf@tmp@tang@i{%
\pgfpointnormalised{}%
- % \pgfpointnormalised stores the angle of the vector in \pgf@tmp
\global\let\pgf@nfold@tmp\pgf@tmp%
}%
\let\pgf@tmp@angle@i\pgf@nfold@tmp%
@@ -208,37 +138,25 @@
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Offsetting a simple section %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\pgf@offset@bezier@segment#1#2#3#4#5{%
- % normalise tangents and normals; this avoids overflow issues later, and we need
- % the normal vector to be of length 1 anyway
\pgf@offset@compute@tangents{#1}{#2}{#3}{#4}%
\pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{#5}%
}
-% this version assumes that the tangents have been precomputed in \pgf@tmp@tang@i and @ii
\def\pgf@offset@bezier@segment@#1#2#3#4#5{%
- % offset A1
- % compute the normal
\pgf@tmp@tang@i
\edef\pgf@tmp@normal@i{\noexpand\pgfqpoint{-\the\pgf@y}{\the\pgf@x}}%
\pgfextract@process\pgf@bezier@offset@i
{\pgfpointadd{\pgfpointscale{#5}{\pgf@tmp@normal@i}}{#1}}%
- % offset A4
\pgf@tmp@tang@ii
\edef\pgf@tmp@normal@ii{\noexpand\pgfqpoint{-\the\pgf@y}{\the\pgf@x}}%
\pgfextract@process\pgf@bezier@offset@iv
{\pgfpointadd{\pgfpointscale{#5}{\pgf@tmp@normal@ii}}{#4}}%
- % now compute A'_2 and A'_3
\pgf@process{\pgfpointdiff{#1}{#4}}%
\pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
\let\pgf@tmp@secantlen\pgfmathresult
\ifdim\pgf@tmp@secantlen pt<0.1pt\relax
- % Edge case: Either the curve is degenerate to a point or it is not simple.
- % Either way we offset A1 and A4, and preserve the vectors A1A2 and A3A4.
\pgfutil@packagewarning{tikz-nfold}{first and last point are too close, expect glitches}%
\pgfextract@process\pgf@bezier@offset@ii
{\pgfpointadd{\pgf@bezier@offset@i}{\pgfpointdiff{#1}{#2}}}%
@@ -248,22 +166,18 @@
\pgfextract@process\pgf@tmp@secant{\pgfpointnormalised{}}%
\pgfmathcrossdot{}{\pgf@tmp@tang@ii}%
\ifdim\pgf@tmp@dot pt<.5pt\relax%
- % this can only happen in non-simple curves
\pgfutil@packagewarning{tikz-nfold}{cosine of \pgf@tmp@dot\space clamped to 0.5 in non-simple segment}%
\def\pgf@tmp@dot{.5}%
\fi%
\pgfmathdivide@{\pgf@tmp@cross}{\pgf@tmp@dot}%
\let\pgf@tmp@tanbeta\pgfmathresult
\pgfmathcrossdot{\pgf@tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}
- % There are cases where we want #5/secantlen to be quite large, so we should not clamp the value here
- % \pgfmathparse{1 + #5/\pgf@tmp@secantlen*(\pgf@tmp@cross - \pgf@tmp@dot*\pgf@tmp@tanbeta)}%
\pgfmath@offset@calculate@scale{\pgf@tmp@secantlen}{\pgf@tmp@cross}{\pgf@tmp@dot}{\pgf@tmp@tanbeta}{#5}%
\pgfextract@process\pgf@bezier@offset@ii{%
\pgfpointadd
{\pgf@bezier@offset@i}
{\pgfqpointscale{\pgfmathresult}{\pgfpointdiff{#1}{#2}}}%
}%
- % third control point
\pgfmathcrossdot{\pgf@tmp@secant}{\pgf@tmp@tang@i}%
\ifdim\pgf@tmp@dot pt<.5pt\relax
\pgfutil@packagewarning{tikz-nfold}{cosine of \pgf@tmp@dot\space clamped to 0.5 in non-simple segment}%
@@ -272,7 +186,6 @@
\pgfmathdivide@{\pgf@tmp@cross}{\pgf@tmp@dot}%
\let\pgf@tmp@tanbeta\pgfmathresult
\pgfmathcrossdot{\pgf@tmp@secant}{\pgfpointnormalised{\pgfpointdiff{#4}{#3}}}%
- % \pgfmathparse{1 + #5/\pgf@tmp@secantlen*(\pgf@tmp@cross - \pgf@tmp@dot*\pgf@tmp@tanbeta)}%
\pgfmath@offset@calculate@scale{\pgf@tmp@secantlen}{\pgf@tmp@cross}{\pgf@tmp@dot}{\pgf@tmp@tanbeta}{#5}%
\pgfextract@process\pgf@bezier@offset@iii{%
\pgfpointadd
@@ -282,12 +195,6 @@
\fi
}
-% calculates 1+#5/#1*(#2-#3*#4)
-% #1 = secantlen
-% #2 = cross
-% #3 = dot
-% #4 = tanbeta
-% #5 = #5 (offset)
\def\pgfmath@offset@calculate@scale#1#2#3#4#5{%
\begingroup
\pgfmathmultiply@{#3}{#4}%
@@ -301,48 +208,24 @@
\endgroup
}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Subdividing and offsetting %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Maximum level of recursion. The theoretical limit to the number of subdivisions in the final curve
-% is given by 2^\pgf@offset@max@recursion
\newcount\pgf@offset@max@recursion
\pgf@offset@max@recursion=4
-%
-% Subdivides a Bezier curve into "simple" segments (according to the definition below),
-% offsets the segments, and draws them. Because offsetting also involves relocating
-% the starting points, these macros come in two variants: with and without a \pgfpathmoveto{}
-% to the new starting point.
-%
-% Interface:
-% #1-#4: control points of the whole Bezier curve
-% #5: offset
\def\pgfoffsetcurve#1#2#3#4#5{%
\pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@move}%
}
\def\pgfoffsetcurvenomove#1#2#3#4#5{%
- \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@nomove}%
+ \pgfoffsetcurvecallback{#1}{#2}{#3}{#4}{#5}{\pgf@nfold@callback@nomove}%
}
-% Arguments:
-% #1-#4: control points of the segment
-% #5: =0 if this is the first segment of the curve, =1 otherwise
-% (checking for #5=0 allows us to draw the curve without interruptions)
\def\pgf@nfold@callback@move#1#2#3#4#5{%
\if#50\pgfpathmoveto{#1}\fi%
\pgfpathcurveto{#2}{#3}{#4}%
}
-% this version never does a moveto at the start. Useful for drawing a path consisting of
-% multiple Bezier curves.
\def\pgf@nfold@callback@nomove#1#2#3#4#5{\pgfpathcurveto{#2}{#3}{#4}}
-% This macro subdivides and offsets a curve and executes a given callback on every offset simple segment.
-% #1-#4: control points of the segment
-% #5: =0 if this is the first segment of the curve, =1 otherwise
-% #6: callback (see \pgf@nfold@callback@move) for the parameters
\def\pgfoffsetcurvecallback#1#2#3#4#5#6{%
\edef\pgf@offset@tmp@callback##1##2##3##4##5{%
\noexpand\pgf@offset@bezier@segment{##1}{##2}{##3}{##4}{#5}%
@@ -352,11 +235,6 @@
}
-% This macro subdivides (but does not offset) a curve and executes a callback on every simple segment.
-% #1-#4: control points
-% #5: recursion limit (decreases on every recursive call)
-% #6: =0 if this is the start of the curve, =1 otherwise
-% #7: callback for output (see above)
\newif\ifpgf@offset@subdivide
\def\pgf@subdividecurve#1#2#3#4#5#6#7{%
\begingroup%
@@ -369,32 +247,24 @@
\endgroup%
}
-% This macro assumes that the curve is defined in \pgf@ctrl@i-\pgf@ctrl@iv
-% and that its tangents have already been computed.
\def\pgf@subdividecurve@#1#2#3{%
\pgf@offset@subdividefalse%
\c@pgf@counta=#1\relax
\advance\c@pgf@counta by -1
- % Use the non-degenerate tangents for the simplicity check
\pgfextract@process\pgf@itoiv{\pgfpointdiff{\pgf@ctrl@i}{\pgf@ctrl@iv}}%
\pgfmathcrossproduct{\pgf@itoiv}{\pgf@tmp@tang@i}%
\let\firstcross\pgfmathresult
\pgfmathcrossproduct{\pgf@itoiv}{\pgf@tmp@tang@ii}%
- % First simplicity check: Are A2 and A3 on the same side of the A1-A4 line?
- % -> compute the sign of the cross products, use the sign function to avoid overflows
- % just give it a pass if one of them is zero, hence 2 and 3 at the end
\ifnum
\ifdim \firstcross pt<0pt -1\else\ifdim \firstcross pt>0pt 1\else 2\fi\fi
=\ifdim\pgfmathresult pt<0pt -1\else\ifdim\pgfmathresult pt>0pt 1\else 3\fi\fi
- \relax % the \relax is important!
+ \relax %
\pgf@offset@subdividetrue%
\else%
- % Second simplicity check: How large is the angle between the tangents in A1 and A4?
\pgfmathdotproduct{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
\ifdim\pgfmathresult pt<.5pt\relax%
\pgf@offset@subdividetrue%
\else
- % Third simplicity check: Put a limit on the lengths of the i-ii and iii-iv vectors combined
\pgf@itoiv
\pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
\pgf@xa=\pgfmathresult pt
@@ -404,7 +274,6 @@
\pgf@process{\pgfpointdiff{\pgf@ctrl@iii}{\pgf@ctrl@iv}}%
\pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}%
\advance\pgf@xb by \pgfmathresult pt
- % veclen(iv-i) < veclen(ii-i) + veclen(iv-iii)
\ifdim\pgf@xa<\pgf@xb
\pgf@offset@subdividetrue
\fi
@@ -412,27 +281,19 @@
\fi%
\ifpgf@offset@subdivide%
\ifnum\c@pgf@counta<0%
- % We hit the recursion limit but the segment is not simple
\pgfutil@packagewarning{tikz-nfold}{Recursion limit reached, glitches may occur. %
Consider increasing \string\pgf@offset@max@recursion}%
- % Try to offset the curve anyway. The result will not be precise,
- % but the code is sufficiently robust to not crash
#3{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#2}%
\else
- % split the non-simple segment and execute recursive calls
\pgf@halfsplitbezier{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}%
- % compute the tangent at the spitting point; this vector is only zero if the curve
- % is degenerate to a point, in which case we can't compute the tangent anyway
\pgfextract@process\pgf@middletangent{%
\pgfpointnormalised{\pgfpointdiff{\pgf@splitbezier@i@iii}{\pgf@splitbezier@i@iv}}}%
\begingroup%
- % we need a group to avoid overwriting variables in recursive calls
\let\pgf@tmp@tang@ii\pgf@middletangent%
\let\pgf@ctrl@i\pgf@splitbezier@i@i%
\let\pgf@ctrl@ii\pgf@splitbezier@i@ii%
\let\pgf@ctrl@iii\pgf@splitbezier@i@iii%
\let\pgf@ctrl@iv\pgf@splitbezier@i@iv%
- % pass on the "start of the curve flag" only to the first term
\pgf@subdividecurve@{\c@pgf@counta}{#2}{#3}%
\endgroup%
\begingroup%
@@ -445,25 +306,16 @@
\endgroup%
\fi%
\else%
- % curve is simple
#3{\pgf@ctrl@i}{\pgf@ctrl@ii}{\pgf@ctrl@iii}{\pgf@ctrl@iv}{#2}%
\fi%
}
-%
-% Offsetting straight lines
-% -------------------------
-%
-% For convenience we also provide macros that offset straight lines. These also come in two variants
-% similar to the macros for curves.
-%
\def\pgfoffsetline#1#2#3{%
\pgfmathparse{#3}%
\pgfoffsetline@{#1}{#2}{\pgfmathresult}{\pgfpointnormalised{\pgfpointdiff{#1}{#2}}}%
}
-% a quicker version in case we already know the tangent and #3 is a number without unit
\def\pgfoffsetline@#1#2#3#4{%
\pgfqpointscale{#3}{#4}%
\pgf@xc=-\pgf@y
diff --git a/graphics/pgf/contrib/tikz-nfold/pgflibrarynfold.code.tex b/graphics/pgf/contrib/tikz-nfold/pgflibrarynfold.code.tex
new file mode 100644
index 0000000000..f593c787b4
--- /dev/null
+++ b/graphics/pgf/contrib/tikz-nfold/pgflibrarynfold.code.tex
@@ -0,0 +1,88 @@
+%% pgflibrarynfold.code.tex
+%% Copyright 2023 Jonathan Schulz
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008-05-04 or later.
+%
+% This work has the LPPL maintenance status 'maintained'.
+%
+% The Current Maintainer of this work is Jonathan Schulz.
+%
+% This work consists of the files
+% pgflibrarybezieroffset.code.tex, pgflibrarynfold.code.tex, pgflibraryoffsetpath.code.tex, tikz-nfold-doc.tex, tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+%
+%
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
+%
+
+
+\usepgflibrary{offsetpath}
+
+
+\newcount\pgf@nfold@index
+\def\pgf@nfold@run@loop{%
+ \pgf@nfold@index=\pgf@nfold@order%
+ \pgf@nfold@run@loop@%
+}
+
+\def\pgf@nfold@run@loop@{%
+ \pgf@nfold@loop@inner%
+ \advance\pgf@nfold@index by -1\relax
+ \ifnum\pgf@nfold@index>0\relax%
+ \pgf@nfold@run@loop@%
+ \fi%
+}
+
+\def\pgf@nfold@loop@inner{%
+ \pgfmathsetmacro{\pgf@nfold@shift@fraction}%
+ {-1+2*(\pgf@nfold@index-1)/(\pgf@nfold@order-1)}%
+ \pgfmathsetmacro{\pgf@nfold@shiftamount}{\pgf@nfold@hwidth*\pgf@nfold@shift@fraction}
+ \pgftransformreset%
+ \parsedpath%
+ \pgfsyssoftpath@flushcurrentpath%
+ \pgf@up@action%
+}
+
+\def\pgf@nfold@compute@widths@from@double{
+ \pgf@x=\pgflinewidth\relax%
+ \pgf@y=\pgf@x\relax%
+ \advance\pgf@x-\pgfinnerlinewidth\relax%
+ \advance\pgf@y+\pgfinnerlinewidth\relax%
+ \pgf@x=.5\pgf@x\relax%
+ \pgf@y=.25\pgf@y\relax%
+}
+
+\def\pgf@nfold@render@cached@softpath{%
+ \pgfscope%
+ \pgf@nfold@compute@widths@from@double%
+ \pgfsetlinewidth\pgf@x%
+ \edef\pgf@nfold@hwidth{\the\pgf@y}%
+ \pgfprocessround{\pgf@nfold@cachedpath}{\pgf@nfold@cachedpath}%
+ \pgf@nfold@parsearrows%
+ \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
+ \pgf@nfold@run@loop%
+ \endpgfscope%
+}
+
+
+\pgfkeys{
+ /pgf/nfold/.code={%
+ \pgf@nfold@order=#1\relax%
+ \ifnum\pgf@nfold@order<1\relax%
+ \pgfutil@packageerror{tikz-nfold}{The key /pgf/nfold must take a value of at least 1, got \the\pgf@nfold@order}{}%
+ \fi%
+ \ifnum\pgf@nfold@order>\pgf@nfold@intersec@numcached\relax
+ \ifdefined\pgfintersectionofpaths\else
+ \pgf@nfold@intersectionsnotloadedtrue
+ \fi
+ \fi
+ },
+ /pgf/nfold/.default=2
+}
+
+\endinput
diff --git a/graphics/pgf/contrib/tikz-nfold/pgflibraryoffsetpath.code.tex b/graphics/pgf/contrib/tikz-nfold/pgflibraryoffsetpath.code.tex
new file mode 100644
index 0000000000..645812ecb1
--- /dev/null
+++ b/graphics/pgf/contrib/tikz-nfold/pgflibraryoffsetpath.code.tex
@@ -0,0 +1,913 @@
+%% pgflibraryoffsetpath.code.tex
+%% Copyright 2023 Jonathan Schulz
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008-05-04 or later.
+%
+% This work has the LPPL maintenance status 'maintained'.
+%
+% The Current Maintainer of this work is Jonathan Schulz.
+%
+% This work consists of the files
+% pgflibrarybezieroffset.code.tex, pgflibrarynfold.code.tex, pgflibraryoffsetpath.code.tex, tikz-nfold-doc.tex, tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+%
+%
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
+%
+
+\usepgflibrary{bezieroffset}
+
+
+
+
+
+
+\gdef\pgf@nfold@cached@miterlimit{10}
+\let\pgf@nfold@old@miterlimit\pgfsetmiterlimit
+\def\pgfsetmiterlimit#1{%
+ \pgf@nfold@old@miterlimit{#1}%
+ \edef\pgf@nfold@cached@miterlimit{#1}%
+}
+
+\global\let\pgf@cached@linejoin=m%
+\let\pgf@nfold@old@setbeveljoin\pgfsetbeveljoin
+\let\pgf@nfold@old@setmiterjoin\pgfsetmiterjoin
+\let\pgf@nfold@old@setroundjoin\pgfsetroundjoin
+\def\pgfsetbeveljoin{%
+ \pgf@nfold@old@setbeveljoin%
+ \let\pgf@cached@linejoin=b%
+}
+\def\pgfsetmiterjoin{%
+ \pgf@nfold@old@setmiterjoin%
+ \let\pgf@cached@linejoin=m%
+}
+\def\pgfsetroundjoin{%
+ \pgf@nfold@old@setroundjoin%
+ \let\pgf@cached@linejoin=r%
+}
+
+
+
+\def\pgf@nfold@miterjoin{
+ \pgfpathlineto{
+ \pgfpointadd{\pgf@nfold@join@centre}{%
+ \pgfpointpolar{\pgf@nfold@firstang+.5*\pgf@nfold@deltaphi+90}%
+ {\pgf@nfold@shiftamount/cos(.5*\pgf@nfold@deltaphi)}%
+ }%
+ }%
+}
+
+\def\pgf@nfold@beveljoin{
+ \pgfmathsetlengthmacro{\bevelouterprotrusion}%
+ {\pgf@nfold@shortenstartjoin pt - .5*\pgflinewidth*abs(tan(.25*\pgf@nfold@deltaphi))}
+ \pgfmathsetmacro{\bevelshorten}{2*\insidepercentage*abs(tan(.25*\pgf@nfold@deltaphi))}
+ \pgfmathparse{\bevelshorten < abs(sin(.5*\pgf@nfold@deltaphi))}
+ \ifnum\pgfmathresult=1\relax
+ \pgfmathsetlengthmacro{\bevelextension}{\bevelouterprotrusion-\bevelshorten*\pgf@nfold@hwidth}
+ \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\bevelextension}}
+ \pgfpathlineto{}
+ \pgfpointadd{\pgf@nfold@join@end}{\pgfpointpolar{\pgf@nfold@secondang}{-\bevelextension}}
+ \pgfpathlineto{}
+ \else
+ \pgf@nfold@miterjoin
+ \fi
+}
+
+\def\pgf@nfold@roundjoin{
+ \ifdim\insidepercentage pt<.5pt\relax
+ \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\pgf@nfold@shortenstartjoin}}
+ \pgfpathlineto{}
+ \pgfmathsetmacro\pgf@tmp@firstang{\pgf@nfold@firstang+90*\turnindicator}
+ \pgfpatharc%
+ {\pgf@tmp@firstang}%
+ {\pgf@tmp@firstang+\pgf@nfold@deltaphi}%
+ {abs(\pgf@nfold@shift@fraction)*\pgf@nfold@hwidth}%
+ \else
+ \pgf@nfold@miterjoin
+ \fi
+}
+
+\def\pgf@nfold@token@join#1#2#3#4#5#6#7#8{%
+ \def\pgf@nfold@join@centre{#1}%
+ \def\pgf@nfold@join@prevend{#2}%
+ \def\pgf@nfold@join@nextstart{#3}%
+ \def\pgf@nfold@firstang{#4}%
+ \def\pgf@nfold@secondang{#5}%
+ \pgfextract@process\pgf@nfold@join@start{%
+ \pgfpointadd{#2}{\pgfpointpolar{\pgf@nfold@firstang+90}{\pgf@nfold@shiftamount}}}%
+ \pgfextract@process\pgf@nfold@join@end{%
+ \pgfpointadd{#3}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@join@start}{\pgf@nfold@join@end}}
+ \pgfpointtaxicabnorm\pgfutil@tempdima
+ \ifdim\pgfutil@tempdima>0.1pt\relax
+ \def\pgf@nfold@deltaphi{#6}%
+ \def\pgf@nfold@shortenstartjoin{#7}%
+ \ifdim\pgf@nfold@deltaphi pt<0pt
+ \def\turnindicator{1}
+ \else
+ \def\turnindicator{-1}
+ \fi
+ \pgfutil@tempdima=\pgf@nfold@shift@fraction pt\relax
+ \pgfutil@tempdima=\turnindicator\pgfutil@tempdima
+ \advance\pgfutil@tempdima by-1pt\relax
+ \pgfutil@tempdima=-.5\pgfutil@tempdima
+ \edef\insidepercentage{\pgf@sys@tonumber\pgfutil@tempdima}%
+ #8%
+ \fi
+}
+
+
+\def\pgf@nfold@process@join{%
+ \pgf@xa=\pgf@nfold@deltaphi@start pt\relax
+ \ifdim\pgf@xa<0pt\relax
+ \pgf@xa=-\pgf@xa
+ \fi
+ \ifdim\pgf@xa>1pt\relax
+ \edef\pgf@nfold@jointype{\pgf@cached@linejoin}
+ \if\pgf@cached@linejoin m%
+ \pgf@xa=.5\pgf@xa
+ \pgfmathcos@{\pgf@sys@tonumber\pgf@xa}
+ \pgf@xa=\pgfmathresult pt\relax
+ \pgf@xa=\pgf@nfold@cached@miterlimit\pgf@xa
+ \ifdim\pgf@xa>1pt\relax
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@miterjoin}
+ \else
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
+ \fi
+ \else
+ \if b\pgf@cached@linejoin\relax
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
+ \else
+ \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@roundjoin}
+ \fi
+ \fi
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@join{\pgf@nfold@cur@first}{\pgf@nfold@prev@segment@end}
+ {\pgf@nfold@cur@movedfirst}{\pgf@nfold@prev@angle@ii}{\pgf@nfold@cur@angle@i}%
+ {\pgf@nfold@deltaphi@start}{\pgf@nfold@shortenstartjoin}{%
+ \expandafter\noexpand\pgf@nfold@tmp@joinmacro%
+ \expandafter\noexpand\ifpgf@nfold@closejoinsedgecase%
+ \pgf@nfold@token@finish@edgecase{\pgf@nfold@cur@movedlast}%
+ \else%
+ \pgf@nfold@token@finish@normal%
+ \fi%
+ }%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi%
+}
+
+
+\def\pgf@nfold@token@finish@normal{%
+ \pgfpathlineto{\pgf@nfold@join@end}%
+}
+
+\def\pgf@nfold@token@finish@edgecase#1{%
+ \pgf@nfold@join@end%
+ \ifdim\insidepercentage pt<.5pt\relax%
+ \pgf@process{\pgfpointadd{#1}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}
+ \fi%
+ \pgfpathlineto{}%
+}
+
+
+
+\newif\ifpgf@nfold@continuesegment
+\newif\ifpgf@nfold@closejoinsedgecase
+\newif\ifpgf@nfold@angletoosharp
+\newif\ifpgf@nfold@intersectionsnotloaded
+\newif\ifpgf@nfold@lastconnsubpath
+
+
+\def\pgf@nfold@process@segment{%
+ \if\pgf@nfold@cur@visible0
+ \if\pgf@nfold@cur@type m
+ \if\pgf@nfold@start@arrowcode1
+ \ifpgf@nfold@lastconnsubpath
+ \if\pgf@nfold@prev@type f
+ \if\pgf@nfold@next@visible1
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@extendtotip{s}{\pgf@nfold@cur@last}{\pgf@nfold@next@angle@i}
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \let\pgf@nfold@cur@type l
+ \let\pgf@nfold@cur@visible1
+ \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@i
+ \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@i
+ \def\pgf@nfold@deltaphi@end{0}
+ \pgf@nfold@angletoosharpfalse
+ \fi
+ \fi%
+ \fi
+ \fi
+ \fi%
+ \else%
+ \let\pgf@nfold@cur@movedfirst\pgf@nfold@cur@first
+ \let\pgf@nfold@cur@movedlast\pgf@nfold@cur@last
+ \def\pgf@nfold@shortenstartjoin{0}
+ \def\pgf@nfold@shortenendjoin{0}
+ \pgf@nfold@closejoinsedgecasefalse
+ \if\pgf@nfold@prev@visible0
+ \pgf@nfold@continuesegmentfalse
+ \else
+ \pgf@nfold@continuesegmenttrue
+ \let\pgf@nfold@deltaphi@start\pgf@nfold@deltaphi@end
+ \pgf@xb=\pgf@nfold@deltaphi@start pt\relax
+ \ifdim\pgf@xb<0pt\relax
+ \pgf@xb=-\pgf@xb
+ \fi
+ \ifpgf@nfold@angletoosharp\else
+ \ifdim\pgf@xb>0.5pt\relax
+ \pgf@yb=.5\pgf@xb
+ \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
+ \pgf@yb=\pgf@nfold@hwidth\relax
+ \pgf@yb=\pgfmathresult\pgf@yb
+ \edef\pgf@nfold@shortenstartjoin{\pgf@sys@tonumber\pgf@yb}
+ \pgfextract@process\pgf@nfold@cur@movedfirst{%
+ \pgfpointadd{\pgf@nfold@cur@first}%
+ {\pgfqpointscale{\pgf@nfold@shortenstartjoin}{\pgf@nfold@cur@tang@i}}}%
+ \if\pgf@nfold@cur@type c
+ \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@supporta}}
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
+ \ifdim\pgfmathresult pt>0.1pt\relax
+ \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
+ \pgfextract@process\pgf@nfold@cur@supporta{\pgfpointadd%
+ {\pgf@nfold@cur@first}%
+ {\pgfqpointscale{\pgfmathresult}{\pgf@nfold@cur@tang@i}}}%
+ \else
+ \let\pgf@nfold@cur@supporta\pgf@nfold@cur@movedfirst
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \if\pgf@nfold@next@visible1
+ \pgfmathsubtract@{\pgf@nfold@next@angle@i}{\pgf@nfold@cur@angle@ii}
+ \pgf@nfold@clampangle
+ \edef\pgf@nfold@deltaphi@end{\pgfmathresult}
+ \pgf@xb=\pgf@nfold@deltaphi@end pt\relax
+ \ifdim\pgf@xb<0pt\relax
+ \pgf@xb=-\pgf@xb
+ \fi
+ \ifdim\pgf@xb>178pt\relax
+ \pgfutil@packagewarning{tikz-nfold}{Angle too sharp, expect visual errors}
+ \pgf@nfold@angletoosharptrue
+ \else
+ \pgf@nfold@angletoosharpfalse
+ \ifdim\pgf@xb>0.5pt\relax
+ \pgf@yb=.5\pgf@xb
+ \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
+ \pgf@yb=\pgf@nfold@hwidth\relax
+ \pgf@yb=\pgfmathresult\pgf@yb
+ \edef\pgf@nfold@shortenendjoin{\pgf@sys@tonumber\pgf@yb}
+ \pgf@yb=-\pgf@yb
+ \pgfextract@process\pgf@nfold@cur@movedlast{%
+ \pgfpointadd{\pgf@nfold@cur@last}%
+ {\pgfqpointscale{-\pgf@nfold@shortenendjoin}{\pgf@nfold@cur@tang@ii}}}%
+ \pgfextract@process\pgf@nfold@cur@movedlast{%
+ \pgfpointadd{\pgf@nfold@cur@last}%
+ {\pgfqpointpolar{\pgf@nfold@cur@angle@ii}{\pgf@yb}}}%
+ \if\pgf@nfold@cur@type c
+ \pgf@process{\pgfpointdiff{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@last}}
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
+ \ifdim\pgfmathresult pt>0.1pt\relax
+ \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
+ \pgfextract@process\pgf@nfold@cur@supportb{\pgfpointadd%
+ {\pgf@nfold@cur@last}%
+ {\pgfqpointscale{-\pgfmathresult}{\pgf@nfold@cur@tang@ii}}}%
+ \else
+ \let\pgf@nfold@cur@supportb\pgf@nfold@cur@movedlast
+ \fi
+ \fi
+ \fi
+ \fi
+ \if\pgf@nfold@cur@type l
+ \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@last}}
+ \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
+ \pgf@xa=\pgf@nfold@shortenstartjoin pt\relax
+ \advance\pgf@xa by\pgf@nfold@shortenendjoin pt\relax
+ \ifdim\pgf@xa>\pgfmathresult pt\relax
+ \pgf@nfold@closejoinsedgecasetrue
+ \fi
+ \fi
+ \fi%
+ \if\pgf@nfold@prev@visible0%
+ \ifpgf@nfold@closejoinsedgecase
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@edgecase@movetostart{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@angle@i}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \else
+ \ifpgf@nfold@angletoosharp\else
+ \if\pgf@nfold@cur@type z\else
+ \pgf@nfold@process@join
+ \fi
+ \fi
+ \fi
+ \let\pgf@nfold@prev@segment@end\pgf@nfold@cur@movedlast
+ \if\pgf@nfold@cur@type i
+ \let\pgf@nfold@connsubpath@tang@i\pgf@nfold@next@tang@i%
+ \let\pgf@nfold@connsubpath@angle@i\pgf@nfold@next@angle@i%
+ \fi
+ \if\pgf@nfold@cur@type l
+ \ifpgf@nfold@closejoinsedgecase\else
+ \edef\pgf@nfold@macrotoadd{%
+ \expandafter\noexpand\ifpgf@nfold@continuesegment%
+ \pgf@nfold@token@lineto@continue%
+ \else%
+ \pgf@nfold@token@lineto%
+ \fi{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \fi
+ \if\pgf@nfold@cur@type o
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \if\pgf@nfold@cur@type z
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \if\pgf@nfold@cur@type c
+ \ifpgf@nfold@continuesegment
+ \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback@continue}
+ \else
+ \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback}%
+ \fi
+ \fi
+ \if\pgf@nfold@cur@type i
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@invisibleline{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi
+ \if\pgf@nfold@next@type t%
+ \ifnum\pgf@nfold@end@arrowcode=1
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@extendtotip{e}{\pgf@nfold@cur@last}{\pgf@nfold@cur@angle@ii}}%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \fi%
+ \fi%
+ \fi%
+}
+
+
+\def\pgf@nfold@addcurvesegment@callback#1#2#3#4#5{%
+ \if#50%
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@curveto{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+ \else%
+ \pgf@nfold@addcurvesegment@callback@continue{#1}{#2}{#3}{#4}{#5}%
+ \fi%
+}
+
+\def\pgf@nfold@addcurvesegment@callback@continue#1#2#3#4#5{%
+ \edef\pgf@nfold@macrotoadd{%
+ \noexpand\pgf@nfold@token@curveto@continue{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
+ }%
+ \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
+}
+
+
+
+\expandafter\def\csname pgf@nfold@intersec@cache@2@3\endcsname{\pgfqpoint{2pt}{0pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@2@4\endcsname{\pgfqpoint{0.94063pt}{-0.33333pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@3@4\endcsname{\pgfqpoint{0.94063pt}{0.33333pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@2@5\endcsname{\pgfqpoint{0.64167pt}{-0.5pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@3@5\endcsname{\pgfqpoint{2pt}{0pt}}
+\expandafter\def\csname pgf@nfold@intersec@cache@4@5\endcsname{\pgfqpoint{0.64167pt}{0.5pt}}
+\def\pgf@nfold@intersec@numcached{5}
+
+\newif\ifpgf@nfold@ontheedge
+\def\pgf@nfold@extendtotip#1#2#3{
+ \ifpgf@nfold@intersectionsnotloaded
+ \pgfutil@packageerror{tikz-nfold}{%
+ If `nfold' is larger than \pgf@nfold@intersec@numcached\space and you use
+ an `Implies' arrow tip you need to say \string\usetikzlibrary{intersections}}{}
+ \else
+ \pgf@nfold@ontheedgetrue
+ \ifnum\pgf@nfold@index>1\relax\ifnum\pgf@nfold@index<\pgf@nfold@order\relax%
+ \pgf@nfold@ontheedgefalse
+ \fi\fi
+ \ifpgf@nfold@ontheedge%
+ \if#1s
+ \pgfpathmoveto{\pgfpointadd{#2}{\pgfpointpolar{#3+90}{\pgf@nfold@shiftamount}}}%
+ \fi
+ \else
+ \ifcsname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname
+ \pgfextract@process\pgf@nfold@arrowintersect
+ {\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname}%
+ \else
+ \pgfintersectionofpaths{
+ \pgfpathmoveto{\pgfqpoint{-1.4pt}{2.65pt}}
+ \pgfpathcurveto{\pgfqpoint{-0.75pt}{1.25pt}}{\pgfqpoint{1pt}{0.05pt}}{\pgfqpoint{2pt}{0pt}}
+ \pgfpathcurveto{\pgfqpoint{1pt}{-0.05pt}}{\pgfqpoint{-0.75pt}{-1.25pt}}{\pgfqpoint{-1.4pt}{-2.65pt}}
+ }{
+ \pgfpathmoveto{\pgfqpoint{-3pt}{\pgf@nfold@shift@fraction pt}}
+ \pgfpathlineto{\pgfqpoint{3pt}{\pgf@nfold@shift@fraction pt}}
+ }
+ \ifnum\pgfintersectionsolutions>0
+ \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointintersectionsolution{1}}%
+ \immediate\write17{tikz-nfold: computed intersection cache@\the\pgf@nfold@index @\the\pgf@nfold@order: \string\pgfqpoint{\the\pgf@x}{\the\pgf@y}^^J}
+ \expandafter\xdef\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
+ \else
+ \pgfutil@packagewarning{tikz-nfold}{did not find intersection}
+ \pgfextract@process\pgf@nfold@arrowintersect{\pgfqpoint{0pt}{\pgf@nfold@shift@fraction pt}}%
+ \fi
+ \fi%
+ \begingroup
+ \pgftransformreset
+ \pgftransformshift{#2}
+ \pgftransformrotate{#3}
+ \if#1s
+ \pgftransformxscale{-1}
+ \fi
+ \pgfutil@tempdima=\pgf@nfold@hwidth
+ \pgfutil@tempdima=\pgf@nfold@shift@fraction\pgfutil@tempdima
+ \pgfextract@process\pgf@nfold@startofextension
+ {\pgfpointtransformed{\pgfqpoint{0pt}{\pgfutil@tempdima}}}
+ \pgftransformshift{\pgfqpoint{.42\pgflinewidth}{0pt}}
+ \pgftransformscale{\pgf@nfold@hwidth}
+ \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointtransformed{\pgf@nfold@arrowintersect}}
+ \global\let\pgf@nfold@startofextension\pgf@nfold@startofextension
+ \global\let\pgf@nfold@arrowintersect\pgf@nfold@arrowintersect
+ \endgroup
+ \if#1s
+ \pgfpathmoveto{\pgf@nfold@arrowintersect}
+ \pgfpathlineto{\pgf@nfold@startofextension}
+ \else\if#1e
+ \pgfpathlineto{\pgf@nfold@arrowintersect}
+ \else
+ \pgfutil@packageerror{tikz-nfold}{Invalid argument to \string\pgf@nfold@extendtotip: \meaning#1}{}
+ \fi\fi
+ \pgftransformreset
+ \fi%
+ \fi%
+}
+
+
+\def\pgf@nfold@start@arrowcode{0}
+\def\pgf@nfold@end@arrowcode{0}
+
+\def\pgf@nfold@parsearrows{
+ \ifpgfutil@tempswa%
+ \expandafter\pgf@nfold@parsearrowmacro\pgf@start@tip@sequence\relax
+ \let\pgf@nfold@start@arrowcode\pgf@nfold@detectedarrow
+ \expandafter\pgf@nfold@parsearrowmacro\pgf@end@tip@sequence\relax
+ \let\pgf@nfold@end@arrowcode\pgf@nfold@detectedarrow
+ \else
+ \def\pgf@nfold@start@arrowcode{0}
+ \def\pgf@nfold@end@arrowcode{0}
+ \fi
+}
+
+\def\pgf@nfold@parsearrowmacro#1{%
+ \def\pgf@nfold@detectedarrow{0}
+ \ifx#1\relax
+ \let\pgf@next\relax
+ \else
+ \ifx#1\pgf@arrow@handle
+ \let\pgf@next\pgf@nfold@parse@arrow@handle
+ \else
+ \ifx#1\pgf@arrow@handle@shorthand@empty
+ \let\pgf@next\pgf@nfold@parse@shorthandempty
+ \else
+ \let\pgf@next\pgfutil@gobble@until@relax
+ \fi
+ \fi
+ \fi
+ \pgf@next
+}
+
+\def\pgf@nfold@param@Implies{Implies}
+
+\def\pgf@nfold@parse@arrow@handle#1{%
+ \def\pgf@tmp{#1}
+ \ifx\pgf@tmp\pgf@nfold@param@Implies
+ \def\pgf@nfold@detectedarrow{1}
+ \fi
+ \pgfutil@gobble@until@relax
+}
+
+\def\pgf@nfold@parse@shorthandempty#1{
+ \expandafter\def\expandafter\pgf@tmp\expandafter{#1}
+ \expandafter\pgf@nfold@parsearrowmacro\pgf@tmp\relax
+ \pgfutil@gobble@until@relax
+}
+
+
+
+\newcount\pgf@nfold@order
+\pgf@nfold@order=1
+
+\def\pgf@nfold@preparenfoldpath{%
+ \ifnum\pgf@nfold@order>1\relax
+ \ifdim\pgfinnerlinewidth>0pt\relax
+ \pgfsyssoftpath@getcurrentpath\pgf@nfold@cachedpath%
+ \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
+ \else
+ \pgfutil@packageerror{tikz-nfold}{Must set \string\pgfinnerlinewidth\space to use nfold, e.g. by setting /tikz/double distance}{}
+ \fi
+ \fi
+}
+
+\let\pgf@nfold@old@path@check@proper\pgf@path@check@proper
+\def\pgf@path@check@proper{%
+ \pgf@nfold@old@path@check@proper%
+ \ifpgfutil@tempswa\else%
+ \pgf@nfold@preparenfoldpath%
+ \fi%
+}
+
+\let\pgf@nfold@old@prepare@start@of@path\pgf@prepare@start@of@path
+\def\pgf@prepare@start@of@path{%
+ \pgf@nfold@old@prepare@start@of@path%
+ \pgf@nfold@preparenfoldpath%
+}
+
+\let\pgf@nfold@old@stroke@inner@line\pgf@stroke@inner@line
+\def\pgf@stroke@inner@line{%
+ \ifnum\pgf@nfold@order>1\relax%
+ \pgf@nfold@render@cached@softpath%
+ \else%
+ \pgf@nfold@old@stroke@inner@line%
+ \fi%
+}
+
+
+
+
+\def\pgf@nfold@parsemoveto#1#2{%
+ \ifx\pgf@cur@conn@subpath\pgfutil@empty%
+ \def\pgf@nfold@parser@last@moveto{{#1}{#2}}%
+ \def\pgf@cur@conn@subpath{\relax}%
+ \else%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processmoveto{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@lastconnsubpathfalse%
+ \pgf@nfold@process@conn@subpath%
+ \let\pgf@nfold@last@closepath@from\pgfutil@empty%
+ \let\pgf@cur@conn@subpath\pgfutil@empty%
+ \pgf@nfold@parser@setupfirst%
+ \def\pgf@nfold@parser@last@moveto{{#1}{#2}}%
+ \fi%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parselineto#1#2{%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processlineto{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parseclosepath#1#2{%
+ \let\pgf@nfold@last@closepath@from\pgf@nfold@parser@previous@pt%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processclosepath{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parsecurveto#1#2{%
+ \edef\pgf@nfold@macrotoadd{\noexpand\pgf@nfold@processcurveto\pgf@nfold@parser@supporta\pgf@nfold@parser@supportb{#1}{#2}}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@parsesoftpath@finish{#1}{#2}%
+}
+
+\def\pgf@nfold@parserect#1#2#3#4{%
+ \pgf@nfold@parsemoveto{#1}{#2}%
+ \pgf@xc=#1\relax
+ \pgf@yc=#2\relax
+ \pgf@xd=#3\relax
+ \pgf@yd=#4\relax
+ \advance\pgf@yc\pgf@yd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parselineto\pgf@temp%
+ \advance\pgf@xc\pgf@xd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parselineto\pgf@temp%
+ \advance\pgf@yc-\pgf@yd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parselineto\pgf@temp%
+ \advance\pgf@xc-\pgf@xd%
+ \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
+ \expandafter\pgf@nfold@parseclosepath\pgf@temp%
+ \pgf@nfold@parsemoveto{#1}{#2}%
+}
+
+
+\def\pgf@nfold@parsesoftpath#1#2{%
+ \let\pgf@cur@conn@subpath\pgfutil@empty%
+ \let\pgf@all@parsed@subpaths\pgfutil@empty%
+ \edef\pgf@nfold@parser@last@moveto{{\the\pgf@path@lastx}{\the\pgf@path@lasty}}%
+ \let\pgf@nfold@last@closepath@from\pgfutil@empty%
+ \pgf@nfold@parser@setupfirst%
+ \expandafter\pgf@nfold@@parsesoftpath#1\pgf@stop{}{}%
+ \let#2\pgf@all@parsed@subpaths%
+}%
+
+\def\pgf@nfold@@parsesoftpath#1#2#3{%
+ \let\pgf@next\pgf@nfold@@parsesoftpath%
+ \ifx#1\pgf@stop%
+ \def\pgf@nfold@macrotoadd{\pgf@nfold@processlast}%
+ \pgf@nfold@addmacro\pgf@cur@conn@subpath%
+ \pgf@nfold@lastconnsubpathtrue%
+ \pgf@nfold@process@conn@subpath%
+ \let\pgf@next\relax%
+ \else%
+ \ifx#1\pgfsyssoftpath@movetotoken%
+ \pgf@nfold@parsemoveto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@linetotoken%
+ \pgf@nfold@parselineto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetosupportatoken%
+ \def\pgf@nfold@parser@supporta{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetosupportbtoken%
+ \def\pgf@nfold@parser@supportb{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath@curvetotoken%
+ \pgf@nfold@parsecurveto{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@closepathtoken%
+ \pgf@nfold@parseclosepath{#2}{#3}%
+ \else%
+ \ifx#1\pgfsyssoftpath@rectcornertoken%
+ \def\pgf@nfold@parser@rectcorner{{#2}{#3}}%
+ \else%
+ \ifx#1\pgfsyssoftpath@rectsizetoken%
+ \expandafter\pgf@nfold@parserect\pgf@nfold@parser@rectcorner{#2}{#3}%
+ \else%
+ \pgfutil@packageerror{tikz-nfold}{Unrecognised soft path token `#1'}{}%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \fi%
+ \pgf@next%
+}%
+
+\def\pgf@nfold@parsesoftpath@finish#1#2{%
+ \def\pgf@nfold@parser@previous@pt{{#1}{#2}}%
+ \let\pgf@nfold@sectolast@segment\pgf@nfold@last@segment%
+ \let\pgf@nfold@last@segment\pgf@nfold@macrotoadd%
+}
+
+\def\pgf@nfold@process@conn@subpath{%
+ \let\pgf@parsed@cur@conn@seg\pgfutil@empty%
+ \ifx\pgf@nfold@last@closepath@from\pgfutil@empty%
+ \expandafter\pgf@nfold@processmoveto\pgf@nfold@parser@last@moveto%
+ \else%
+ \expandafter\pgf@nfold@processmoveto\pgf@nfold@last@closepath@from%
+ \expandafter\pgf@nfold@processinvisibleline\pgf@nfold@parser@last@moveto%
+ \fi%
+ \pgf@cur@conn@subpath%
+ \let\pgf@nfold@macrotoadd\pgf@parsed@cur@conn@seg%
+ \pgf@nfold@addmacro\pgf@all@parsed@subpaths%
+}
+
+
+\def\pgf@nfold@processmoveto#1#2{%
+ \pgf@nfold@process@moveup%
+ \let\pgf@nfold@next@type=m%
+ \let\pgf@nfold@next@visible=0%
+ \edef\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
+ \pgf@nfold@process@segment%
+}%
+
+\def\pgf@nfold@process@line@common#1#2#3{%
+ \pgf@nfold@process@moveup%
+ \pgfextract@process\pgf@tmp@tang@i{\pgfpointnormalised{}\global\let\pgf@nfold@tmp\pgf@tmp}
+ \let\pgf@nfold@next@type=#3%
+ \let\pgf@nfold@next@visible=1%
+ \let\pgf@nfold@next@tang@i\pgf@tmp@tang@i
+ \let\pgf@nfold@next@tang@ii\pgf@tmp@tang@i
+ \let\pgf@nfold@next@angle@i\pgf@nfold@tmp
+ \let\pgf@nfold@next@angle@ii\pgf@nfold@tmp
+ \let\pgf@nfold@next@first\pgf@nfold@cur@last
+ \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
+ \pgf@nfold@process@segment%
+}
+
+\def\pgf@nfold@processlineto#1#2{%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
+ \pgfpointtaxicabnorm\pgf@xa%
+ \ifdim\pgf@xa>.1pt\relax%
+ \pgf@nfold@process@line@common{#1}{#2}{l}%
+ \fi%
+}%
+
+\def\pgf@nfold@processcurveto#1#2#3#4#5#6{%
+ \pgf@nfold@process@moveup%
+ \pgf@offset@compute@tangents{\pgf@nfold@cur@last}{\pgf@x#1\pgf@y#2}{\pgf@x#3\pgf@y#4}{\pgf@x#5\pgf@y#6}%
+ \let\pgf@nfold@next@type=c%
+ \let\pgf@nfold@next@visible=1%
+ \let\pgf@nfold@next@tang@i=\pgf@tmp@tang@i
+ \let\pgf@nfold@next@tang@ii=\pgf@tmp@tang@ii
+ \let\pgf@nfold@next@angle@i\pgf@tmp@angle@i
+ \let\pgf@nfold@next@angle@ii\pgf@tmp@angle@ii
+ \let\pgf@nfold@next@first\pgf@nfold@cur@last
+ \def\pgf@nfold@next@supporta{\pgf@x#1\pgf@y#2}
+ \def\pgf@nfold@next@supportb{\pgf@x#3\pgf@y#4}
+ \def\pgf@nfold@next@last{\pgf@x#5\pgf@y#6}
+ \pgf@nfold@process@segment%
+}%
+
+\def\pgf@nfold@processclosepath#1#2{%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
+ \pgfpointtaxicabnorm\pgf@xa%
+ \ifdim\pgf@xa<0.1pt\relax%
+ \pgf@nfold@process@closepath@zerolength{#1}{#2}%
+ \else%
+ \pgf@nfold@process@line@common{#1}{#2}{o}%
+ \fi%
+}%
+
+\def\pgf@nfold@process@closepath@zerolength#1#2{%
+ \pgf@nfold@process@moveup%
+ \let\pgf@nfold@next@type=z%
+ \let\pgf@nfold@next@visible=1%
+ \let\pgf@nfold@next@tang@i\pgf@nfold@connsubpath@tang@i
+ \let\pgf@nfold@next@tang@ii\pgf@nfold@connsubpath@tang@i
+ \let\pgf@nfold@next@angle@i\pgf@nfold@connsubpath@angle@i
+ \let\pgf@nfold@next@angle@ii\pgf@nfold@connsubpath@angle@i
+ \let\pgf@nfold@next@first\pgf@nfold@cur@last
+ \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
+ \pgf@nfold@process@segment%
+}
+
+\def\pgf@nfold@processinvisibleline#1#2{%
+ \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
+ \pgfpointtaxicabnorm\pgf@xa%
+ \ifdim\pgf@xa>.1pt\relax%
+ \pgf@nfold@process@line@common{#1}{#2}{i}%
+ \else%
+ \begingroup%
+ \let\pgf@nfold@process@segment\relax%
+ \pgf@nfold@sectolast@segment%
+ \global\let\pgf@nfold@tmp\pgf@nfold@next@tang@ii%
+ \endgroup%
+ \pgfextract@process\pgf@nfold@next@first{\pgfpointdiff{\pgf@nfold@tmp}{\pgfqpoint{#1}{#2}}}%
+ \pgf@nfold@tmp%
+ \pgf@nfold@process@line@common{#1}{#2}{i}%
+ \fi%
+}%
+
+\def\pgf@nfold@processlast{%
+ \pgf@nfold@process@moveup%
+ \let\pgf@nfold@next@type=t%
+ \let\pgf@nfold@next@visible=0%
+ \pgf@nfold@process@segment%
+}
+
+\def\pgf@nfold@addmacro#1{%
+ \expandafter\expandafter\expandafter\gdef%
+ \expandafter\expandafter\expandafter#1%
+ \expandafter\expandafter\expandafter{%
+ \expandafter#1\pgf@nfold@macrotoadd}%
+}
+
+
+
+\def\pgf@nfold@token@lineto#1#2#3{%
+ \pgfoffsetline@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
+}
+
+\def\pgf@nfold@token@lineto@continue#1#2#3{%
+ \pgfoffsetlinenomove@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
+}
+
+\def\pgf@nfold@token@invisibleline#1#2#3{%
+ \pgfqpointscale{\pgf@nfold@shiftamount}{#3}%
+ \pgf@xc=-\pgf@y%
+ \pgf@y=\pgf@x%
+ \pgf@x=\pgf@xc%
+ \pgfpathmoveto{\pgfpointadd{}{#2}}%
+}
+
+\def\pgf@nfold@token@curveto#1#2#3#4#5#6{%
+ \def\pgf@tmp@tang@i{#5}%
+ \def\pgf@tmp@tang@ii{#6}%
+ \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
+ \pgfpathmoveto{\pgf@bezier@offset@i}%
+ \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
+}
+
+\def\pgf@nfold@token@curveto@continue#1#2#3#4#5#6{%
+ \def\pgf@tmp@tang@i{#5}%
+ \def\pgf@tmp@tang@ii{#6}%
+ \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
+ \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
+}
+
+\def\pgf@nfold@token@closepath{%
+ \pgfpathclose%
+}
+
+\def\pgf@nfold@token@edgecase@movetostart#1#2{%
+ \pgfpathmoveto{\pgfpointadd%
+ {#1}{\pgfpointpolar{#2+90}{\pgf@nfold@shiftamount}}}%
+}
+
+
+\def\pgf@nfold@parser@setupfirst{%
+ \let\pgf@nfold@next@type=f%
+ \let\pgf@nfold@next@visible=0%
+ \edef\pgf@nfold@next@last{\pgf@x\the\pgf@path@lastx\pgf@y\the\pgf@path@lasty}%
+}
+
+\def\pgf@nfold@clampangle{
+ \ifdim\pgfmathresult pt<-180pt\relax
+ \pgfutil@tempdima=\pgfmathresult pt
+ \advance\pgfutil@tempdima by 360pt
+ \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
+ \else\ifdim\pgfmathresult pt>180pt\relax
+ \pgfutil@tempdima=\pgfmathresult pt
+ \advance\pgfutil@tempdima by -360pt
+ \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
+ \fi\fi
+}
+
+
+\def\pgf@nfold@process@moveup{%
+ \let\pgf@nfold@prev@type\pgf@nfold@cur@type%
+ \let\pgf@nfold@prev@visible\pgf@nfold@cur@visible%
+ \let\pgf@nfold@prev@tang@i\pgf@nfold@cur@tang@i%
+ \let\pgf@nfold@prev@tang@ii\pgf@nfold@cur@tang@ii%
+ \let\pgf@nfold@prev@angle@i\pgf@nfold@cur@angle@i%
+ \let\pgf@nfold@prev@angle@ii\pgf@nfold@cur@angle@ii%
+ \let\pgf@nfold@prev@first\pgf@nfold@cur@first%
+ \let\pgf@nfold@prev@supporta\pgf@nfold@cur@supporta%
+ \let\pgf@nfold@prev@supportb\pgf@nfold@cur@supportb%
+ \let\pgf@nfold@prev@last\pgf@nfold@cur@last%
+ \let\pgf@nfold@cur@type\pgf@nfold@next@type%
+ \let\pgf@nfold@cur@visible\pgf@nfold@next@visible%
+ \let\pgf@nfold@cur@tang@i\pgf@nfold@next@tang@i%
+ \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@ii%
+ \let\pgf@nfold@cur@angle@i\pgf@nfold@next@angle@i%
+ \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@ii
+ \let\pgf@nfold@cur@first\pgf@nfold@next@first%
+ \let\pgf@nfold@cur@supporta\pgf@nfold@next@supporta%
+ \let\pgf@nfold@cur@supportb\pgf@nfold@next@supportb%
+ \let\pgf@nfold@cur@last\pgf@nfold@next@last%
+}
+
+
+\def\pgfoffsetpath#1#2{%
+ \begingroup
+ \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
+ \pgf@x=\pgf@nfold@parsed@hwidth\relax
+ \ifdim\pgf@x<0pt\relax
+ \pgf@x=-\pgf@x
+ \def\pgf@nfold@shift@fraction{-1}
+ \else
+ \def\pgf@nfold@shift@fraction{1}
+ \fi
+ \edef\pgf@nfold@parsed@hwidth{\the\pgf@x}
+ \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathfraction#1#2#3{%
+ \begingroup
+ \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
+ \pgfmathsetmacro\pgf@nfold@shift@fraction{#3}
+ \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathindex#1#2#3#4{%
+ \begingroup
+ \pgfmathsetmacro\pgf@nfold@shift@fraction{-1+2*(#3-1)/(#4-1)}
+ \pgfoffsetpathqfraction{#1}{#2}{\pgf@nfold@shift@fraction}
+ \endgroup
+}
+
+\def\pgfoffsetpathqfraction#1#2#3{%
+ \begingroup
+ \pgf@x=#2\relax
+ \edef\pgf@nfold@hwidth{\the\pgf@x}
+ \edef\pgf@nfold@shift@fraction{#3}
+ \pgf@x=\pgf@nfold@shift@fraction\pgf@x\relax
+ \edef\pgf@nfold@shiftamount{\pgf@sys@tonumber\pgf@x}
+ \pgfprocessround{#1}{\pgf@nfold@cachedpath}%
+ \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
+ \pgftransformreset%
+ \parsedpath%
+ \endgroup
+}
+
+\endinput
diff --git a/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.pdf b/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.pdf
index 9df9c937ac..8dad39e27f 100644
--- a/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.pdf
+++ b/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.pdf
Binary files differ
diff --git a/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.tex b/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.tex
index 46132fb7f5..094924d2e8 100644
--- a/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.tex
+++ b/graphics/pgf/contrib/tikz-nfold/tikz-nfold-doc.tex
@@ -1,4 +1,4 @@
-%% tikz-nfold.sty
+%% tikz-nfold-doc.tex
%% Copyright 2023 Jonathan Schulz
%
% This work may be distributed and/or modified under the
@@ -13,8 +13,12 @@
%
% The Current Maintainer of this work is Jonathan Schulz.
%
-% This work consists of the files pgflibrarybezieroffset.code.tex,
-% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+% This work consists of the files
+% pgflibrarybezieroffset.code.tex, pgflibrarynfold.code.tex, pgflibraryoffsetpath.code.tex, tikz-nfold-doc.tex, tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
+%
+%
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
+%
\documentclass[12pt,a4paper]{article}
@@ -27,7 +31,6 @@
\usepackage{parskip}
\usepackage[margin=2.5cm]{geometry}
-% recommended order: 1) hyperref 2) amsthm 3) cleveref 4) \newtheorem
\usepackage[colorlinks]{hyperref}
\usepackage{amsmath}
\usepackage{amsthm}
@@ -38,7 +41,6 @@
\theoremstyle{definition}
\newtheorem{definition}{Definition}[section]
-%\newcommand{\todo}[1]{{\color{red}\bfseries#1}}
\newcommand{\tikzdouble}{\texttt{/tikz/double}}
\newcommand{\nfold}{\texttt{nfold}}
\newcommand{\tikznfold}{\texttt{/tikz/nfold}}
@@ -52,7 +54,6 @@
\newcommand{\uv}{\vec{u}}
\newcommand{\vv}{\vec{v}}
-% to be used in pre=... to stop the proparation of warnings outside of tkzexample environments
\makeatletter
\def\disablewarnings{\def\pgfutil@packagewarning##1##2{}}
\makeatother
@@ -209,6 +210,19 @@ This package is by no means perfect, and even if it were, there would still be s
\subsection{Impossible or very hard to fix}
\begin{itemize}
+ \item Self-intersecting paths do not have the expected intersections:
+\begin{tkzexample}[latex=4.5cm]
+\begin{tikzpicture}
+ \draw[double distance=5pt, line width=1pt]
+ (0,2.5) -- (1,2.5) (1,3) -- (1,2)
+ (2,2) -- (3,2) rectangle (4,3);
+ \node[right] at (0,3.5) {double:};
+ \draw[double distance=5pt, line width=1pt, nfold]
+ (0,.5) -- (1,.5) (1,1) -- (1,0)
+ (2,0) -- (3,0) rectangle (4,1);
+ \node[right] at (0,1.5) {nfold:};
+\end{tikzpicture}
+\end{tkzexample}
\item \nfold{} struggles with high curvatures and wide paths: Let $\kappa(t)$ be the curvature of the path in a given point, and let $\texttt{double distance} = \alpha$. If $\kappa(t) > \frac{2}{\alpha}$ (i.e. the radius of the osculating circle is smaller than half the width of the path) for some $0 \leq t \leq 1$, the output of \nfold{} will not be correct:
\begin{tkzexample}[latex=4.25cm]
\begin{tikzpicture}
@@ -268,12 +282,14 @@ This package is by no means perfect, and even if it were, there would still be s
\section{The basic layer \texttt{pgf} commands}
+This package contains three \emph{pgf} libraries building upon one another: \texttt{bezieroffset}, \texttt{offsetpath}, and \nfold. All of these are contained in the \emph{TikZ} library \nfold.
+
\subsection{Offsetting curves}
-This package provides some basic layer commands for offsetting curves and straight lines. Use
+This library provides some basic layer commands for offsetting curves and straight lines. Use
\begin{verbatim}
\usepgflibrary{bezieroffset}
\end{verbatim}
-to only import the base layer library. The following commands are provided:
+to only import this base layer library. The following commands are provided:
\begin{itemize}
\item \verb|\pgfoffsetcurve{pt1}{pt2}{pt3}{pt4}{distance}|\\%
This macro draws the parallel of a Bézier curve. The first four parameters are the control points of the Bézier curve (e.g.\ in the form of \verb|\pgfpoint{}{}|), the fifth parameter is the distance by which the curve should be offset. A negative value offsets the curve in the opposite direction. This macro begins with a \verb|\pgfpointmoveto| to the offset of \texttt{pt1}.
@@ -286,7 +302,7 @@ to only import the base layer library. The following commands are provided:
\end{itemize}
\subsection{Offsetting paths}
-The following macros are part of the TikZ library \nfold{} and offset an entire soft path.
+The following macros are part of the pgf library \texttt{offsetpath} and offset the whole softpath.
\begin{itemize}
\item \verb|\pgfoffsetpath{softpath}{distance}|\\%
This macro offsets \texttt{softpath} by \texttt{distance}. The latter may be negative.
@@ -295,7 +311,7 @@ The following macros are part of the TikZ library \nfold{} and offset an entire
\item \verb|\pgfoffsetpathqfraction{softpath}{hwidth}{fraction}|\\%
This macro is a quicker version of the previous macro does not parse the input values using the \texttt{pgfmath}-engine.
\item \verb|\pgfoffsetpathindex{softpath}{width}{i}{n}|\\%
- In this convenience method, \texttt{i} and \texttt{n} are integers with $1 \leq i \leq n$. It calls the previous macro with \texttt{fraction=-1.0} for \texttt{i=1} and with \texttt{fraction=1.0} for \texttt{i=n} and is thus capable of reproducing the output of \texttt{/tikz/nfold=n} (albeit in a less efficient way).
+ In this convenience method, \texttt{i} and \texttt{n} are integers with $1 \leq i \leq n$. It calls the previous macro with \texttt{fraction=-1.0} for \texttt{i=1} and with \texttt{fraction=1.0} for \texttt{i=n}, hence it is capable of reproducing the output of \texttt{/tikz/nfold=n} (albeit in a less efficient way).
\end{itemize}
In the following example we see how \verb|\pgfoffsetpath{..}{0pt}| reproduces the input path (rendered in black) and how \verb|\pgfoffsetpathfraction{..}{8pt}{0}| differs.
\begin{tkzexample}[latex=4cm]
@@ -329,6 +345,7 @@ Here we see how the commands can be used to customise $n$-fold paths:
\section{Version history}
\begin{itemize}
+ \item \textbf{v1.0.0}: Restructure and bug fixes
\item \textbf{v0.1.3}: Bug fixes
\item \textbf{v0.1.2}: Bug fixes
\item \textbf{v0.1.1}: Closing paths and structural changes
@@ -497,7 +514,6 @@ Note that $-\tfrac{\pi}{3} \leq \beta \leq \tfrac{\pi}{3}$ (and hence $\cos(\bet
\end{equation}
and all of these terms can be computed directly from dot and cross products of vectors between the original control points. To summarise, let $\vv_{ij} := \overrightarrow{A_iA_j}$, and let $\vv_0$, $\vv_1$ be the normalised tangents at $t=0$ and $t=1$, respectively (see \cref{subsec:stabilisation} how they are computed). Then
\begin{equation}
-% for checking
\overline{A'_1A'_2} = \overline{A_1A_2} + \frac{d}{\overline{A_1A_4}^2}\cdot\left(\vv_{12} \times \vv_{14} - \vv_{12}\cdot\vv_{14} \frac{\vv_{14}\times\tv_1}{\vv_{14}\cdot\tv_1} \right) \ .
\end{equation}
Let furthermore $\uv_{ij} := \vv_{ij}/|\vv_{ij}|$ be the normalised vectors. Then we find
diff --git a/graphics/pgf/contrib/tikz-nfold/tikzlibrarynfold.code.tex b/graphics/pgf/contrib/tikz-nfold/tikzlibrarynfold.code.tex
index 342191b0ad..799fa6b4d9 100644
--- a/graphics/pgf/contrib/tikz-nfold/tikzlibrarynfold.code.tex
+++ b/graphics/pgf/contrib/tikz-nfold/tikzlibrarynfold.code.tex
@@ -1,4 +1,4 @@
-%% tikz-nfold.sty
+%% tikzlibrarynfold.code.tex
%% Copyright 2023 Jonathan Schulz
%
% This work may be distributed and/or modified under the
@@ -13,1312 +13,30 @@
%
% The Current Maintainer of this work is Jonathan Schulz.
%
-% This work consists of the files pgflibrarybezieroffset.code.tex,
-% tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
-
-\usetikzlibrary{arrows.meta}
-\usepgflibrary{bezieroffset}
-
-
-%
-% General idea
-% ============
-%
-% In order to offset a path, we must first analyse and slightly modify it. For example,
-% the start and end points of segments need to be relocated slightly in order to make room
-% for the joins, and most curves must be subdivided for the offsetting algorithm. To avoid
-% redundant computations in n-fold paths, we pre-compute as much data as possible and store
-% all this information in a "parsed path" macro. The structure of the parsed path resembles
-% the structure of a pgf softpath, but it consists of different tokens.
-%
-
-
-
-%
-% Intercepting join settings
-% --------------------------
-%
-% The current settings of the line joins are not stored in any TeX registers; instead, direct system
-% calls are made to apply the settings. Therefore, we need to modify the pgf macros in order
-% to cache the current settings.
-%
-
-% According to the pgf documentation, miter limit=10 is the default value,
-% but I couldn't find and verify this setting in the pgf code
-\gdef\pgf@nfold@cached@miterlimit{10}
-\let\pgf@nfold@old@miterlimit\pgfsetmiterlimit
-\def\pgfsetmiterlimit#1{%
- \pgf@nfold@old@miterlimit{#1}%
- \edef\pgf@nfold@cached@miterlimit{#1}%
-}
-
-% default line join is "miter"
-\global\let\pgf@cached@linejoin=m% % b = bevel, m=miter, r=round
-\let\pgf@nfold@old@setbeveljoin\pgfsetbeveljoin
-\let\pgf@nfold@old@setmiterjoin\pgfsetmiterjoin
-\let\pgf@nfold@old@setroundjoin\pgfsetroundjoin
-\def\pgfsetbeveljoin{%
- \pgf@nfold@old@setbeveljoin%
- % do NOT change this globally! Needs to be changed back at the end of groups for scoping reasons
- \let\pgf@cached@linejoin=b%
-}
-\def\pgfsetmiterjoin{%
- \pgf@nfold@old@setmiterjoin%
- \let\pgf@cached@linejoin=m%
-}
-\def\pgfsetroundjoin{%
- \pgf@nfold@old@setroundjoin%
- \let\pgf@cached@linejoin=r%
-}
-
-
-%
-% Joining offset lines
-% --------------------
-%
-% One of the more difficult aspects is joining the segments of an offset path. Without this step,
-% the path would be interrupted or self-intersect whenever there is a non-zero angle between
-% two segments. This code reproduces the existing line joins "bevel", "miter" and "round".
-%
-
-\def\pgf@nfold@miterjoin{
- % The tip of the miter join is computed starting from the original (unshifted) centre of the join;
- % we then move orthorgonal to the average of the old and new angle
- \pgfpathlineto{
- \pgfpointadd{\pgf@nfold@join@centre}{%
- \pgfpointpolar{\pgf@nfold@firstang+.5*\pgf@nfold@deltaphi+90}% do not change
- {\pgf@nfold@shiftamount/cos(.5*\pgf@nfold@deltaphi)}%
- }%
- }%
-}
-
-\def\pgf@nfold@beveljoin{
- % The bevel join for one component line consists of three parts:
- % 1) an extension of the ingoing line,
- % 2) a middle line, angled at the average of the incoming and outgoing line,
- % 3) an extension of the outgoing line.
- % Different components of the ingoing and outgoing lines have a constant distance from each other.
- % For a good-looking output, the mittle parts of the component lines thus should also have a constant distance,
- % which is a non-trivial condition. To generate such an output the outer lines get a bevel-like join
- % and the inner lines get a miter-like join; the threshold depends on deltaphi.
- % We first compute by how much the outermost line must be continued from the beginning of the join.
- % The protrusion amount must be lowered by a little bit for a rather complicated reason: The offset would be
- % dead on if the outermost offset line were centered on the _edge_ of the wide line, but we want to draw
- % the outside line _fully inside_ the wide line. The factor of tan(deltaphi/4) can be derived, but is not obvious.
- \pgfmathsetlengthmacro{\bevelouterprotrusion}%
- {\pgf@nfold@shortenstartjoin pt - .5*\pgflinewidth*abs(tan(.25*\pgf@nfold@deltaphi))}
- % The following applies to middle lines only: We compute by how much they need to be shortened so the distance
- % between the lines in the join is correct.
- \pgfmathsetmacro{\bevelshorten}{2*\insidepercentage*abs(tan(.25*\pgf@nfold@deltaphi))}
- % This threshold decides if the inside line has a bevel or a miter join
- \pgfmathparse{\bevelshorten < abs(sin(.5*\pgf@nfold@deltaphi))}
- \ifnum\pgfmathresult=1\relax
- \pgfmathsetlengthmacro{\bevelextension}{\bevelouterprotrusion-\bevelshorten*\pgf@nfold@hwidth}
- \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\bevelextension}}
- \pgfpathlineto{}
- \pgfpointadd{\pgf@nfold@join@end}{\pgfpointpolar{\pgf@nfold@secondang}{-\bevelextension}}
- \pgfpathlineto{}
- \else
- \pgf@nfold@miterjoin
- \fi
-}
-
-\def\pgf@nfold@roundjoin{
- % The outer half of the lines get arcs, the others get miters
- \ifdim\insidepercentage pt<.5pt\relax
- \pgfpointadd{\pgf@nfold@join@start}{\pgfpointpolar{\pgf@nfold@firstang}{\pgf@nfold@shortenstartjoin}}
- \pgfpathlineto{}
- % TODO needs unit tests for all cases left, right, across the 360 gap etc.
- \pgfmathsetmacro\pgf@tmp@firstang{\pgf@nfold@firstang+90*\turnindicator}
- \pgfpatharc%
- {\pgf@tmp@firstang}%
- {\pgf@tmp@firstang+\pgf@nfold@deltaphi}%
- {abs(\pgf@nfold@shift@fraction)*\pgf@nfold@hwidth}%
- \else
- \pgf@nfold@miterjoin
- \fi
-}
-
-% The handler that will be added to the parsed path
-% #1: The centre of the join
-% #2: The end point of the first segment
-% #3: The starting point of the second segment
-% #4: The angle of the first segment
-% #5: The angle of the second segment
-% #6: deltaphi in the range [-180, 180]
-% #7: the distance between #1 and #2
-% #8: the join + finish macro
-\def\pgf@nfold@token@join#1#2#3#4#5#6#7#8{%
- \def\pgf@nfold@join@centre{#1}%
- \def\pgf@nfold@join@prevend{#2}%
- \def\pgf@nfold@join@nextstart{#3}%
- \def\pgf@nfold@firstang{#4}%
- \def\pgf@nfold@secondang{#5}%
- % Offset the start and end of this join
- \pgfextract@process\pgf@nfold@join@start{%
- \pgfpointadd{#2}{\pgfpointpolar{\pgf@nfold@firstang+90}{\pgf@nfold@shiftamount}}}%
- \pgfextract@process\pgf@nfold@join@end{%
- \pgfpointadd{#3}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}%
- \pgf@process{\pgfpointdiff{\pgf@nfold@join@start}{\pgf@nfold@join@end}}
- % Check if the start of this segment is very close to the end of the previous segment.
- % In that case we don't need a join at all
- \pgfpointtaxicabnorm\pgfutil@tempdima
- \ifdim\pgfutil@tempdima>0.1pt\relax
- \def\pgf@nfold@deltaphi{#6}%
- \def\pgf@nfold@shortenstartjoin{#7}%
- % First step: Check if left or right turn (-1=left, 1=right)
- \ifdim\pgf@nfold@deltaphi pt<0pt
- \def\turnindicator{1}
- \else
- \def\turnindicator{-1}
- \fi
- % \insidepercentage: between 0.0 and 1.0;
- % 0=no distance to cover in the join, 1=maximum distance to cover
- \pgfutil@tempdima=\pgf@nfold@shift@fraction pt\relax
- \pgfutil@tempdima=\turnindicator\pgfutil@tempdima
- \advance\pgfutil@tempdima by-1pt\relax
- \pgfutil@tempdima=-.5\pgfutil@tempdima
- % \insidepercentage = .5 * (1 - \turnindicator*\pgf@nfold@shift@fraction)
- \edef\insidepercentage{\pgf@sys@tonumber\pgfutil@tempdima}%
- #8%
- \fi
-}
-
-
-%
-% Parser: Join handler
-%
-\def\pgf@nfold@parser@handlejoin{%
- % \pgf@xa := abs(deltaphi@start)
- \pgf@xa=\pgf@nfold@deltaphi@start pt\relax
- \ifdim\pgf@xa<0pt\relax
- \pgf@xa=-\pgf@xa
- \fi
- % Skip the entire join if abs(deltaphi) is too small
- \ifdim\pgf@xa>1pt\relax
- \edef\pgf@nfold@jointype{\pgf@cached@linejoin}
- \if\pgf@cached@linejoin m% \ifx is not needed because both are only one character
- % miter join
- % First we implement the miter limit: If the angle is too sharp, the miter join is replaced
- % by a bevel join. This is controlled by /tikz/miter limit=..., initially 10.
- \pgf@xa=.5\pgf@xa
- \pgfmathcos@{\pgf@sys@tonumber\pgf@xa}
- \pgf@xa=\pgfmathresult pt\relax
- \pgf@xa=\pgf@nfold@cached@miterlimit\pgf@xa
- % Switch to bevel if miterlimit*cos(.5*abs(deltaphi)) <= 1
- \ifdim\pgf@xa>1pt\relax
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@miterjoin}
- \else
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
- \fi
- \else
- \if b\pgf@cached@linejoin\relax
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@beveljoin}
- \else
- \def\pgf@nfold@tmp@joinmacro{\pgf@nfold@roundjoin}
- \fi
- \fi
- % The last parameter is a macro to be called when this segment of the join is non-trivial.
- % It consists of
- % - the macro to actually draw the join,
- % - either finish@normal or finish@edgecase.
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@join{\pgf@nfold@cur@first}{\pgf@nfold@prev@segment@end}
- {\pgf@nfold@cur@movedfirst}{\pgf@nfold@prev@angle@ii}{\pgf@nfold@cur@angle@i}%
- {\pgf@nfold@deltaphi@start}{\pgf@nfold@shortenstartjoin}{%
- \expandafter\noexpand\pgf@nfold@tmp@joinmacro%
- \expandafter\noexpand\ifpgf@nfold@closejoinsedgecase%
- \pgf@nfold@token@finish@edgecase{\pgf@nfold@cur@movedlast}%
- \else%
- \pgf@nfold@token@finish@normal%
- \fi%
- }%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi% end if abs(deltaphi) > 1
-}
-
-
-% All non-trivial joins connect to the end of the join, which is the starting point of the next segment.
-% Note that this entire macro is skipped by if the start and end of the join coincide, so we never create a zero length segment here.
-%
-% There is one edge case here: If two subsequent joins are so close that \pgf@nfold@cur@movedlast
-% and \pgf@nfold@cur@movedfirst exchange places *and* we are on the outside of the first join
-% (implying that we are on the inside of the second join), the first join must not connect all the way to
-% to \pgf@nfold@cur@movedfirst, because that would overshoot the second join. Instead we connect to
-% \pgf@nfold@cur@movedlast (which is *closer* to the first join than \pgf@nfold@cur@movedfirst in this edge case).
-% To accomodate for the vertical offset we connect to \pgf@nfold@join@end which is the vertical
-% offset of \pgf@nfold@cur@movedlast by definition.
-\def\pgf@nfold@token@finish@normal{%
- \pgfpathlineto{\pgf@nfold@join@end}%
-}
-
-% parameter #1: @movedlast of the next segment
-\def\pgf@nfold@token@finish@edgecase#1{%
- \pgf@nfold@join@end%
- \ifdim\insidepercentage pt<.5pt\relax%
- \pgf@process{\pgfpointadd{#1}{\pgfpointpolar{\pgf@nfold@secondang+90}{\pgf@nfold@shiftamount}}}
- \fi%
- \pgfpathlineto{}%
-}
-
-
-%
-% Main rendering pipeline
-% -----------------------
-%
-
-% This stores whether the current segment should begin with a moveto to its offset
-\newif\ifpgf@nfold@continuesegment
-% This stores whether we are in some edge case of very close joins, see below for details
-\newif\ifpgf@nfold@closejoinsedgecase
-% This stores whether we are in an error case where we need to avoid dividing by zero
-\newif\ifpgf@nfold@angletoosharp
-% This stores whether we need the intersections library for an arrow tip but it is not loaded
-\newif\ifpgf@nfold@intersectionsnotloaded
-% This stores whether the currently processed connected sub-path is the final one on this path
-\newif\ifpgf@nfold@lastconnsubpath
-
-
-\def\pgf@nfold@parser@handlesegment{%
- \if\pgf@nfold@cur@visible0
- % first, last and moveto are invisible
- \if\pgf@nfold@cur@type m
- % We don't need to do anything for a moveto; if a visible segment follows, it will move to
- % its starting location by itself. However, we might need to draw the arrow tip extension
- % at the start (if present).
- % Draw a tip extension only if all of the following conditions are met:
- % 1. There is an Implies tip at the start of this path
- % 2. We are currently on the last connected sub-path of this path
- % 3. The next segment is visible
- % 4. This moveto is the first segment on this path
- \if\pgf@nfold@start@arrowcode1
- \ifpgf@nfold@lastconnsubpath
- \if\pgf@nfold@prev@type f
- \if\pgf@nfold@next@visible1
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@extendtotip{s}{\pgf@nfold@cur@last}{\pgf@nfold@next@angle@i}
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- % hack: We make the next segment believe that this segment was a lineto
- % so the path does not get interrupted
- \let\pgf@nfold@cur@type l
- \let\pgf@nfold@cur@visible1
- \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@i
- \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@i
- \def\pgf@nfold@deltaphi@end{0}
- \pgf@nfold@angletoosharpfalse
- \fi
- \fi%
- \fi
- \fi
- \fi%
- \else%
- \let\pgf@nfold@cur@movedfirst\pgf@nfold@cur@first
- \let\pgf@nfold@cur@movedlast\pgf@nfold@cur@last
- %%% Step 1: Make room for joins if necessary
- % In order to make room for the join, it may be necessary to shorten the current segment
- % at the start and/or the end. In here we store by how much the segment needs to be shortened.
- \def\pgf@nfold@shortenstartjoin{0}
- \def\pgf@nfold@shortenendjoin{0}
- \pgf@nfold@closejoinsedgecasefalse
- % Step 1.1: Make room for the join at the start if needed
- \if\pgf@nfold@prev@visible0
- \pgf@nfold@continuesegmentfalse
- \else
- \pgf@nfold@continuesegmenttrue
- % deltaphi@start can be recycled from deltaphi@end;
- % \ifpgf@nfold@angletoosharp is also still set
- \let\pgf@nfold@deltaphi@start\pgf@nfold@deltaphi@end
- % set \pgf@xb := abs(deltaphi@start)
- \pgf@xb=\pgf@nfold@deltaphi@start pt\relax
- \ifdim\pgf@xb<0pt\relax
- \pgf@xb=-\pgf@xb
- \fi
- \ifpgf@nfold@angletoosharp\else
- \ifdim\pgf@xb>0.5pt\relax
- % make room for the start join if the angle is nonzero;
- % shortenstartjoin := hwidth*tan(.5*abs(deltaphi@start))
- \pgf@yb=.5\pgf@xb
- \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
- \pgf@yb=\pgf@nfold@hwidth\relax
- \pgf@yb=\pgfmathresult\pgf@yb
- \edef\pgf@nfold@shortenstartjoin{\pgf@sys@tonumber\pgf@yb}
- \pgfextract@process\pgf@nfold@cur@movedfirst{%
- \pgfpointadd{\pgf@nfold@cur@first}%
- {\pgfqpointscale{\pgf@nfold@shortenstartjoin}{\pgf@nfold@cur@tang@i}}}%
- % If the current segment is a curve, we need to relocate @supporta point as well,
- % as otherwise the @first point could overtake it
- \if\pgf@nfold@cur@type c
- \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@supporta}}
- \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
- \ifdim\pgfmathresult pt>0.1pt\relax
- % regular curves (supporta != first):
- % Increase dist(first, supporta) to sqrt(a^2 + b^2) where a=dist(first, supporta) and b=shortenstart. This way, the order of first and supporta is guaranteed to be preserved, and the change to supporta is as small as reasonably possible.
- \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
- \pgfextract@process\pgf@nfold@cur@supporta{\pgfpointadd%
- {\pgf@nfold@cur@first}%
- {\pgfqpointscale{\pgfmathresult}{\pgf@nfold@cur@tang@i}}}%
- \else
- % special treatment for singular curves (supporta = first) to avoid rounding error glitches.
- % In this special case, a slight corner at the end of the join is unavoidable unless we
- % also relocate @supportb, which may have unintended side effects
- \let\pgf@nfold@cur@supporta\pgf@nfold@cur@movedfirst
- \fi
- \fi
- \fi
- \fi
- \fi
- % Step 1.2: Make room for the join at the end if needed
- \if\pgf@nfold@next@visible1
- % Compute the angle difference at the end (between -180 and +180 degrees)
- % using \pgfmathsubtract@ is more readable and no less efficient than computing this manually
- \pgfmathsubtract@{\pgf@nfold@next@angle@i}{\pgf@nfold@cur@angle@ii}
- \pgf@nfold@clampangle
- % Edge case handling: If the next segment is a closepath and has length zero, deltaphi is set
- % to zero to prevent glitches (a zero length segment has no well-defined angle anyway)
- \edef\pgf@nfold@deltaphi@end{\pgfmathresult}
- \pgf@xb=\pgf@nfold@deltaphi@end pt\relax
- \ifdim\pgf@xb<0pt\relax
- \pgf@xb=-\pgf@xb
- \fi
- \ifdim\pgf@xb>178pt\relax
- \pgfutil@packagewarning{tikz-nfold}{Angle too sharp, expect visual errors}
- \pgf@nfold@angletoosharptrue
- \else
- \pgf@nfold@angletoosharpfalse
- \ifdim\pgf@xb>0.5pt\relax
- % make room for the start join if the angle is nonzero
- % shortenendjoin := hwidth*tan(.5*abs(deltaphi@end))
- \pgf@yb=.5\pgf@xb
- \pgfmathtan@{\pgf@sys@tonumber\pgf@yb}
- \pgf@yb=\pgf@nfold@hwidth\relax
- \pgf@yb=\pgfmathresult\pgf@yb
- \edef\pgf@nfold@shortenendjoin{\pgf@sys@tonumber\pgf@yb}
- \pgf@yb=-\pgf@yb
- \pgfextract@process\pgf@nfold@cur@movedlast{%
- % the use of the minus sign is fine here because \pgf@nfold@shortenendjoin >= 0.0
- \pgfpointadd{\pgf@nfold@cur@last}%
- {\pgfqpointscale{-\pgf@nfold@shortenendjoin}{\pgf@nfold@cur@tang@ii}}}%
- \pgfextract@process\pgf@nfold@cur@movedlast{%
- \pgfpointadd{\pgf@nfold@cur@last}%
- {\pgfqpointpolar{\pgf@nfold@cur@angle@ii}{\pgf@yb}}}%
- \if\pgf@nfold@cur@type c
- % Same procedure as above: relocate supportb if we have a curve
- \pgf@process{\pgfpointdiff{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@last}}
- \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
- \ifdim\pgfmathresult pt>0.1pt\relax
- \pgfmathveclen@{\pgfmathresult}{\pgf@sys@tonumber\pgf@yb}
- \pgfextract@process\pgf@nfold@cur@supportb{\pgfpointadd%
- {\pgf@nfold@cur@last}%
- % can use qpointscale and a minus because \pgfmathresult is guaranteed to be positive
- {\pgfqpointscale{-\pgfmathresult}{\pgf@nfold@cur@tang@ii}}}%
- \else
- \let\pgf@nfold@cur@supportb\pgf@nfold@cur@movedlast
- \fi
- \fi
- \fi
- \fi
- % Step 1.3: Detect an edge case
- % This edge case appears whenever the current segment is such a short line that we would
- % have to reduce its length to less than zero to make room for the joins. In such cases,
- % the line is not drawn at all, and slight modifications must be made to the joins to ensure
- % a correct output (i.e. one join is immediately followed by the next without a segment in between).
- %
- % This edge case can appear for curves as well, but they are much harder to deal with.
- \if\pgf@nfold@cur@type l
- % No need to check for \pgf@nfold@inputsegmentclosepath as it should not be followed by any further segments
- % Now: Check if the total amount of shortening is larger than the length of the segment
- \pgf@process{\pgfpointdiff{\pgf@nfold@cur@first}{\pgf@nfold@cur@last}}
- \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}
- \pgf@xa=\pgf@nfold@shortenstartjoin pt\relax
- \advance\pgf@xa by\pgf@nfold@shortenendjoin pt\relax
- \ifdim\pgf@xa>\pgfmathresult pt\relax
- \pgf@nfold@closejoinsedgecasetrue
- \fi
- \fi
- \fi% end if next segment visible
- %
- % Step 2.1: Draw the join at the start if applicable
- %
- \if\pgf@nfold@prev@visible0%
- \ifpgf@nfold@closejoinsedgecase
- % If the previous segment is a moveto and the current segment is a "close joins" edge case,
- % nothing needs to be drawn here (the relevant draw call will be made at the join of the subsequent
- % segment). We must therefore make sure that we move to the correct end point of this segment.
- % Counterintuitively, this is given by the offset of \pgf@nfold@cur@movedFIRST since the start and end
- % are reversed in the edge case.
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@edgecase@movetostart{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@angle@i}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \else
- % If we draw the join when the start angle is close to 180 degrees, we get a division by zero
- \ifpgf@nfold@angletoosharp\else
- \if\pgf@nfold@cur@type z\else
- \pgf@nfold@parser@handlejoin
- \fi
- \fi
- \fi
- % Step 2.2: Store information that may be needed later
- % Step 2.2.1: Store where the current (non-offset) end point was relocated
- % in order to make space for the end join. This may be used if the next
- % segment begins with a join
- \let\pgf@nfold@prev@segment@end\pgf@nfold@cur@movedlast
- % Step 2.2.2: Store the tangent of the first proper segment of closed path.
- % This is needed in case the \pgfpathclose-segment has length zero,
- % since in that case its tangent cannot be computed.
- \if\pgf@nfold@cur@type i
- \let\pgf@nfold@connsubpath@tang@i\pgf@nfold@next@tang@i%
- \let\pgf@nfold@connsubpath@angle@i\pgf@nfold@next@angle@i%
- \fi
- %
- % Step 3: Draw the new segment.
- %
- % The value of \ifpgf@nfold@continuesegment decides whether we start with a moveto.
- \if\pgf@nfold@cur@type l
- % In the edge case, one join is followed immediately by the next. The line segment
- % thus has a negative length and will be skipped.
- \ifpgf@nfold@closejoinsedgecase\else
- \edef\pgf@nfold@macrotoadd{%
- \expandafter\noexpand\ifpgf@nfold@continuesegment%
- \pgf@nfold@token@lineto@continue%
- \else%
- \pgf@nfold@token@lineto%
- \fi{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \fi
- \if\pgf@nfold@cur@type o
- \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \if\pgf@nfold@cur@type z
- % zero and non-zero closepath's differ in the join handling, but are identical in rendering
- \def\pgf@nfold@macrotoadd{\pgf@nfold@token@closepath}%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- \if\pgf@nfold@cur@type c
- \ifpgf@nfold@continuesegment
- \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback@continue}
- \else
- \pgf@subdividecurve{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@supporta}{\pgf@nfold@cur@supportb}{\pgf@nfold@cur@movedlast}{\pgf@offset@max@recursion}{0}{\pgf@nfold@addcurvesegment@callback}%
- \fi
- \fi
- \if\pgf@nfold@cur@type i
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@invisibleline{\pgf@nfold@cur@movedfirst}{\pgf@nfold@cur@movedlast}{\pgf@nfold@cur@tang@i}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi
- % Step 4: Extend into the arrow tip at the end (if present)
- \if\pgf@nfold@next@type t%
- \ifnum\pgf@nfold@end@arrowcode=1
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@extendtotip{e}{\pgf@nfold@cur@last}{\pgf@nfold@cur@angle@ii}}%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \fi%
- \fi%
- \fi% end if current visible
-}
-
-
-\def\pgf@nfold@addcurvesegment@callback#1#2#3#4#5{%
- \if#50%
- \edef\pgf@nfold@macrotoadd{%
- % The subdivision algorithm has already computed the tangents
- \noexpand\pgf@nfold@token@curveto{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
- \else%
- \pgf@nfold@addcurvesegment@callback@continue{#1}{#2}{#3}{#4}{#5}%
- \fi%
-}
-
-\def\pgf@nfold@addcurvesegment@callback@continue#1#2#3#4#5{%
- % The subdivision algorithm has already computed the tangents
- \edef\pgf@nfold@macrotoadd{%
- \noexpand\pgf@nfold@token@curveto@continue{#1}{#2}{#3}{#4}{\pgf@tmp@tang@i}{\pgf@tmp@tang@ii}%
- }%
- \pgf@nfold@addmacro\pgf@parsed@cur@conn@seg%
-}
-
-
-% Rendering arrow tips
-% --------------------
-
-% Precomputed intersections
-%
-% For arrows of order n > 2 with an Implies tip, the constituent parts of the n-fold arrow
-% end somewhere in the middle of the tip. The exact end point must be computed using
-% the intersections library. To speed up compilation times, the intersection points are precomputed
-% up to n = 5. If your document contains arrows of order 6 or larger, consider adding those
-% as well; the values are output in the log file.
-\expandafter\def\csname pgf@nfold@intersec@cache@2@3\endcsname{\pgfqpoint{2pt}{0pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@2@4\endcsname{\pgfqpoint{0.94063pt}{-0.33333pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@3@4\endcsname{\pgfqpoint{0.94063pt}{0.33333pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@2@5\endcsname{\pgfqpoint{0.64167pt}{-0.5pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@3@5\endcsname{\pgfqpoint{2pt}{0pt}}
-\expandafter\def\csname pgf@nfold@intersec@cache@4@5\endcsname{\pgfqpoint{0.64167pt}{0.5pt}}
-% intersections are precomputed up to this order
-\def\pgf@nfold@intersec@numcached{5}
-
-% This macro extends the arrow body to the tips
-% #1: s=start, e=end
-% #2: start/end point of the path
-% #3: angle
-\newif\ifpgf@nfold@ontheedge
-\def\pgf@nfold@extendtotip#1#2#3{
- \ifpgf@nfold@intersectionsnotloaded
- \pgfutil@packageerror{tikz-nfold}{%
- If `nfold' is larger than \pgf@nfold@intersec@numcached\space and you use
- an `Implies' arrow tip you need to say \string\usetikzlibrary{intersections}}{}
- \else
- \pgf@nfold@ontheedgetrue
- % Do not extend the arrow for index=1 and index=order, it already ends in the right place
- \ifnum\pgf@nfold@index>1\relax\ifnum\pgf@nfold@index<\pgf@nfold@order\relax%
- \pgf@nfold@ontheedgefalse
- \fi\fi
- \ifpgf@nfold@ontheedge%
- % the extension at the start needs a moveto to the correct starting point
- \if#1s
- \pgfpathmoveto{\pgfpointadd{#2}{\pgfpointpolar{#3+90}{\pgf@nfold@shiftamount}}}%
- \fi
- \else
- % Step 1: Find the intersection of the arrow's path with the head
- \ifcsname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname
- \pgfextract@process\pgf@nfold@arrowintersect
- {\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname}%
- \else
- % the intersection has not been precomputed, thus compute on the fly here
- \pgfintersectionofpaths{
- % specify the tip
- \pgfpathmoveto{\pgfqpoint{-1.4pt}{2.65pt}}
- \pgfpathcurveto{\pgfqpoint{-0.75pt}{1.25pt}}{\pgfqpoint{1pt}{0.05pt}}{\pgfqpoint{2pt}{0pt}}
- \pgfpathcurveto{\pgfqpoint{1pt}{-0.05pt}}{\pgfqpoint{-0.75pt}{-1.25pt}}{\pgfqpoint{-1.4pt}{-2.65pt}}
- }{
- % extend the body to intersect the tip
- \pgfpathmoveto{\pgfqpoint{-3pt}{\pgf@nfold@shift@fraction pt}}
- \pgfpathlineto{\pgfqpoint{3pt}{\pgf@nfold@shift@fraction pt}}
- }
- \ifnum\pgfintersectionsolutions>0
- \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointintersectionsolution{1}}%
- \immediate\write17{tikz-nfold: computed intersection cache@\the\pgf@nfold@index @\the\pgf@nfold@order: \string\pgfqpoint{\the\pgf@x}{\the\pgf@y}^^J}
- % add the new intersection to the cache
- \expandafter\xdef\csname pgf@nfold@intersec@cache@\the\pgf@nfold@index @\the\pgf@nfold@order\endcsname{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}
- \else
- % this is a failsafe and should never be reached
- \pgfutil@packagewarning{tikz-nfold}{did not find intersection}
- \pgfextract@process\pgf@nfold@arrowintersect{\pgfqpoint{0pt}{\pgf@nfold@shift@fraction pt}}%
- \fi
- \fi% if precomputed
- % Step 2: Extend the arrow body to the intersection point.
- % If the tip is at the beginning of the path, we have to move to the intersection
- % and then draw a line to the "regular" starting point. The subsequent segment then
- % should omit its moveto.
- % If the tip is at the end, we are already in the right position and only need to extend
- % the current path to the intersection point.
- \begingroup
- \pgftransformreset
- \pgftransformshift{#2}
- \pgftransformrotate{#3}
- \if#1s
- \pgftransformxscale{-1}
- \fi
- % we don't want to undo the shift by .42\pgflinewidth after the scaling
- \pgfutil@tempdima=\pgf@nfold@hwidth
- \pgfutil@tempdima=\pgf@nfold@shift@fraction\pgfutil@tempdima
- \pgfextract@process\pgf@nfold@startofextension
- {\pgfpointtransformed{\pgfqpoint{0pt}{\pgfutil@tempdima}}}
- % 0.5 - 0.06 = 0.42
- \pgftransformshift{\pgfqpoint{.42\pgflinewidth}{0pt}}
- \pgftransformscale{\pgf@nfold@hwidth}
- \pgfextract@process\pgf@nfold@arrowintersect{\pgfpointtransformed{\pgf@nfold@arrowintersect}}
- \global\let\pgf@nfold@startofextension\pgf@nfold@startofextension
- \global\let\pgf@nfold@arrowintersect\pgf@nfold@arrowintersect
- \endgroup
- \if#1s
- \pgfpathmoveto{\pgf@nfold@arrowintersect}
- % This is precisely the start of the body, shifted vertically
- \pgfpathlineto{\pgf@nfold@startofextension}
- \else\if#1e
- \pgfpathlineto{\pgf@nfold@arrowintersect}
- \else
- \pgfutil@packageerror{tikz-nfold}{Invalid argument to \string\pgf@nfold@extendtotip: \meaning#1}{}
- \fi\fi
- \pgftransformreset
- \fi% if 1 < i < nArrows
- \fi% if intersections is needed and not loaded
-}
-
-% Parsing the arrow tips
-% ----------------------
-%
-% We need to detect if the user has set Implies[] arrows at the start and/or end tip.
-% To do so, we parse \pgf@start@tip@sequence. If the user specifies Implies[] manually,
-% we find that
-% pgf@start@tip@sequence=\pgf@arrow@handle{Implies}{...}
-% However, in other cases (like tikz-cd) we may find
-% \pgf@arrow@handle@shorthand@empty {\csname pgf@ar@means@tikzcd implies cap\endcsname }
-% In such cases we must expand the first parameter once and then match as above.
-
-% Set global defaults
-\def\pgf@nfold@start@arrowcode{0}
-\def\pgf@nfold@end@arrowcode{0}
-
-\def\pgf@nfold@parsearrows{
- \ifpgfutil@tempswa% this is set in \pgfusepath and stores whether we draw arrow tips at all
- \expandafter\pgf@nfold@parsearrowmacro\pgf@start@tip@sequence\relax
- \let\pgf@nfold@start@arrowcode\pgf@nfold@detectedarrow
- \expandafter\pgf@nfold@parsearrowmacro\pgf@end@tip@sequence\relax
- \let\pgf@nfold@end@arrowcode\pgf@nfold@detectedarrow
- \else
- \def\pgf@nfold@start@arrowcode{0}
- \def\pgf@nfold@end@arrowcode{0}
- \fi
-}
-
-\def\pgf@nfold@parsearrowmacro#1{%
- \def\pgf@nfold@detectedarrow{0}
- \ifx#1\relax
- \let\pgf@next\relax
- \else
- \ifx#1\pgf@arrow@handle
- % found \pgf@arrow@handle{...}, now parse the first parameter
- \let\pgf@next\pgf@nfold@parse@arrow@handle
- \else
- \ifx#1\pgf@arrow@handle@shorthand@empty
- \let\pgf@next\pgf@nfold@parse@shorthandempty
- \else
- % found nothing
- \let\pgf@next\pgfutil@gobble@until@relax
- \fi
- \fi
- \fi
- \pgf@next
-}
-
-\def\pgf@nfold@param@Implies{Implies}
-
-\def\pgf@nfold@parse@arrow@handle#1{%
- \def\pgf@tmp{#1}
- \ifx\pgf@tmp\pgf@nfold@param@Implies
- \def\pgf@nfold@detectedarrow{1}
- \fi
- \pgfutil@gobble@until@relax
-}
-
-\def\pgf@nfold@parse@shorthandempty#1{
- % Expand #1 once (\pgf@arrow@handle@shorthand@empty is just an identity operator)
- \expandafter\def\expandafter\pgf@tmp\expandafter{#1}
- \expandafter\pgf@nfold@parsearrowmacro\pgf@tmp\relax
- % still need to gobble the rest of the orginal arrow definition
- \pgfutil@gobble@until@relax
-}
-
-
-%
-% Hooking into pgf's rendering pipeline
-% -------------------------------------
-%
-% The new code has to be injected into \pgfusepath (pgfcorepathusage.code.tex). For rendering the new paths,
-% \pgf@stroke@inner@line is a natural choice as this is where /tikz/double is rendered. However, we also
-% need to disable rendering the ordinary path, which is not as easy. In the future I will make a pull request
-% to TikZ to simplify such injections.
-%
-% The call to draw the path comes right before \pgf@stroke@inner@line. The macro before \pgf@stroke@inner@line
-% is either \pgf@path@check@proper or \pgf@prepare@start@of@path (depending on the result of the proper check).
-% We therefore must inject code into both of them to see if nfold is enabled. If it is, we call the old macro,
-% cache and delete the current softpath (so the call to \pgfsyssoftpath@invokecurrentpath has no effect), then we
-% restore and offset the cached softpath in \pgf@stroke@inner@line.
-%
-% The macros \pgf@path@check@proper and \pgf@prepare@start@of@path are also used in \pgf@up@draw@arrows@only,
-% so we must make sure that the latter is unaffected by the modifications. Luckily, this turns out not to be
-% a problem - the only macros that are called after the modified ones are \pgf@add@arrow@at@start and
-% \pgf@add@arrow@at@end, which do not change their behaviour even if we modify the paths.
-%
-
-\newcount\pgf@nfold@order
-\pgf@nfold@order=1
-
-\def\pgf@nfold@preparenfoldpath{%
- \ifnum\pgf@nfold@order>1\relax
- \ifdim\pgfinnerlinewidth>0pt\relax
- % Hack the rendering pipeline: There is a \pgfsyssoftpath@invokecurrentpath call following
- % which we do not want if nfold is active. We therefore clear the current path here
- % and then perform the nfold drawing in our modification of \pgf@stroke@inner@line
- \pgfsyssoftpath@getcurrentpath\pgf@nfold@cachedpath%
- \pgfsyssoftpath@setcurrentpath\pgfutil@empty%
- \else
- \pgfutil@packageerror{tikz-nfold}{Must set \string\pgfinnerlinewidth\space to use nfold, e.g. by setting /tikz/double distance}{}
- \fi
- \fi
-}
-
-\let\pgf@nfold@old@path@check@proper\pgf@path@check@proper
-\def\pgf@path@check@proper{%
- \pgf@nfold@old@path@check@proper%
- \ifpgfutil@tempswa\else%
- % if \pgfutil@tempswa is false, this is the last macro we can overwrite before the draw call.
- % Otherwise, we inject into \pgf@prepare@start@of@path%
- \pgf@nfold@preparenfoldpath%
- \fi%
-}
-
-\let\pgf@nfold@old@prepare@start@of@path\pgf@prepare@start@of@path
-\def\pgf@prepare@start@of@path{%
- \pgf@nfold@old@prepare@start@of@path%
- \pgf@nfold@preparenfoldpath%
-}
-
-\let\pgf@nfold@old@stroke@inner@line\pgf@stroke@inner@line
-\def\pgf@stroke@inner@line{%
- \ifnum\pgf@nfold@order>1\relax%
- \pgf@nfold@render@cached@softpath%
- \else%
- % Old behaviour
- \pgf@nfold@old@stroke@inner@line%
- \fi%
-}
-
-
-%
-% Parsing the soft path
-% ---------------------
-%
-% A significant part of the code below is based on pgfmoduledecorations.code.tex (c) 2019 Mark Wibrow and Till Tantau.
-% Quite similar to decorations we parse the current soft path and put it into a form that makes it easier
-% to iterate over.
-%
+% This work consists of the files
+% pgflibrarybezieroffset.code.tex, pgflibrarynfold.code.tex, pgflibraryoffsetpath.code.tex, tikz-nfold-doc.tex, tikzlibrarynfold.code.tex, tikz-nfold-doc.tex, and tikz-nfold-doc.pdf.
%
-
-
%
-% In order to correctly implement \pgfpathclose we already need to know about
-% the \pgfpathclose (and the penultimate point) at the beginning of this
-% connected sub-path as these data affect the first/last join.
-% We therefore parse one connected sub-path of the softpath and store it in a modified
-% form in \pgf@cur@conn@subpath. When reaching the end of the connected sub-path we call
-% the proper parser to turn \pgf@cur@conn@subpath into a parsed path. We do this for
-% all connected sub-paths and concatenate all the parsed paths.
+% A commented version of this file can be found on https://github.com/jonschz/tikz-nfold .
%
-\def\pgf@nfold@parsesoftpath#1#2{%
- \let\pgf@cur@conn@subpath\pgfutil@empty%
- \let\pgf@all@parsed@subpaths\pgfutil@empty%
- \edef\pgf@nfold@parser@last@moveto{{\the\pgf@path@lastx}{\the\pgf@path@lasty}}%
- \let\pgf@nfold@last@closepath@from\pgfutil@empty%
- \pgf@nfold@parse@setupfirst%
- \expandafter\pgf@nfold@@parsesoftpath#1\pgf@stop{}{}%
- \let#2\pgf@all@parsed@subpaths%
-}%
-
-\def\pgf@nfold@@parsesoftpath#1#2#3{%
- \let\pgf@next\pgf@nfold@@parsesoftpath%
- \ifx#1\pgf@stop%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parselast}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \pgf@nfold@lastconnsubpathtrue%
- \pgf@nfold@process@conn@subpath%
- \let\pgf@next\relax%
- \else%
- \ifx#1\pgfsyssoftpath@movetotoken%
- \ifx\pgf@cur@conn@subpath\pgfutil@empty%
- % This case happens for the very first segment or for double movetos.
- % We need special treatment here, as otherwise the arrow tip extension
- % does not work correctly. The \pgf@nfold@parsemoveto will be called
- % in \pgf@nfold@process@conn@subpath.
- \def\pgf@nfold@parser@last@moveto{{#2}{#3}}%
- % Make sure \pgf@cur@conn@subpath is no longer empty so double movetos are not
- % treated the same as single movetos. This is also relevant to arrow tip extensions
- \def\pgf@cur@conn@subpath{\relax}%
- \else%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parsemoveto{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \pgf@nfold@lastconnsubpathfalse%
- % A moveto marks the beginning/end of one connected sub-path
- \pgf@nfold@process@conn@subpath%
- \let\pgf@nfold@last@closepath@from\pgfutil@empty%
- \let\pgf@cur@conn@subpath\pgfutil@empty%
- % set up "first" again which may be needed for the arrow tip extension
- \pgf@nfold@parse@setupfirst%
- \def\pgf@nfold@parser@last@moveto{{#2}{#3}}%
- \fi
- \else%
- \ifx#1\pgfsyssoftpath@linetotoken%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parselineto{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \ifx#1\pgfsyssoftpath@curvetosupportatoken%
- \def\pgf@nfold@parse@supporta{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath@curvetosupportbtoken%
- \def\pgf@nfold@parse@supportb{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath@curvetotoken%
- \edef\pgf@nfold@macrotoadd{\noexpand\pgf@nfold@parsecurveto\pgf@nfold@parse@supporta\pgf@nfold@parse@supportb{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \ifx#1\pgfsyssoftpath@closepathtoken%
- \let\pgf@nfold@last@closepath@from\pgf@nfold@parser@previous@pt%
- \def\pgf@nfold@macrotoadd{\pgf@nfold@parseclosepath{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \ifx#1\pgfsyssoftpath@rectcornertoken%
- \def\pgf@nfold@parse@rectcorner{{#2}{#3}}%
- \else%
- \ifx#1\pgfsyssoftpath@rectsizetoken%
- \edef\pgf@nfold@macrotoadd{\noexpand\pgf@nfold@parserect\pgf@nfold@parse@rectcorner{#2}{#3}}%
- \pgf@nfold@addmacro\pgf@cur@conn@subpath%
- \else%
- \pgfutil@packageerror{tikz-nfold}{Unrecognised soft path token `#1'}{}%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \fi%
- \def\pgf@nfold@parser@previous@pt{{#2}{#3}}%
- % store the last two segments, as they might be needed for zero-length \pgfpathclose-segments
- \let\pgf@nfold@sectolast@segment\pgf@nfold@last@segment%
- \let\pgf@nfold@last@segment\pgf@nfold@macrotoadd%
- \pgf@next}%
-
-\def\pgf@nfold@process@conn@subpath{%
- \let\pgf@parsed@cur@conn@seg\pgfutil@empty%
- \ifx\pgf@nfold@last@closepath@from\pgfutil@empty%
- \expandafter\pgf@nfold@parsemoveto\pgf@nfold@parser@last@moveto%
- \else%
- % This connected sub-path ends on a closepath. In order to get
- % the join right, we prepend the current sub-path with an invisible line
- % identical to the line of the \pgfpathclose.
- \expandafter\pgf@nfold@parsemoveto\pgf@nfold@last@closepath@from%
- \expandafter\pgf@nfold@parseinvisibleline\pgf@nfold@parser@last@moveto%
- \fi%
- \pgf@cur@conn@subpath%
- \let\pgf@nfold@macrotoadd\pgf@parsed@cur@conn@seg%
- \pgf@nfold@addmacro\pgf@all@parsed@subpaths%
-}
-
-%
-% Values for \pgf@nfold@next@type:
-% f=first, m=moveto, c=curveto, l=lineto, r=rect, o=closepath, z=zero length closepath, t=last, i=invisibleline
-%
-
-\def\pgf@nfold@parsemoveto#1#2{%
- \pgf@nfold@parser@moveup%
- \let\pgf@nfold@next@type=m%
- \let\pgf@nfold@next@visible=0%
- \edef\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
- \pgf@nfold@parser@handlesegment%
-}%
-
-
-% Common code for parselineto and parseclosepath
-\def\pgf@nfold@parse@line@common#1#2#3{%
- \pgf@nfold@parser@moveup%
- \pgfextract@process\pgf@tmp@tang@i{\pgfpointnormalised{}\global\let\pgf@nfold@tmp\pgf@tmp}
- \let\pgf@nfold@next@type=#3%
- \let\pgf@nfold@next@visible=1%
- \let\pgf@nfold@next@tang@i\pgf@tmp@tang@i
- \let\pgf@nfold@next@tang@ii\pgf@tmp@tang@i
- \let\pgf@nfold@next@angle@i\pgf@nfold@tmp
- \let\pgf@nfold@next@angle@ii\pgf@nfold@tmp
- \let\pgf@nfold@next@first\pgf@nfold@cur@last
- \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
- \pgf@nfold@parser@handlesegment%
-}
-
-\def\pgf@nfold@parselineto#1#2{%
- % the current end is still stored in next@last because parser@moveup has not been called yet
- \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
- \pgfpointtaxicabnorm\pgf@xa%
- % remove degenerate line segments (reduces glitches)
- \ifdim\pgf@xa>.1pt\relax%
- \pgf@nfold@parse@line@common{#1}{#2}{l}%
- \fi%
-}%
-
-\def\pgf@nfold@parsecurveto#1#2#3#4#5#6{%
- \pgf@nfold@parser@moveup%
- \pgf@offset@compute@tangents{\pgf@nfold@cur@last}{\pgf@x#1\pgf@y#2}{\pgf@x#3\pgf@y#4}{\pgf@x#5\pgf@y#6}%
- \let\pgf@nfold@next@type=c%
- \let\pgf@nfold@next@visible=1%
- % the following only need to be set if visible=1
- \let\pgf@nfold@next@tang@i=\pgf@tmp@tang@i
- \let\pgf@nfold@next@tang@ii=\pgf@tmp@tang@ii
- \let\pgf@nfold@next@angle@i\pgf@tmp@angle@i
- \let\pgf@nfold@next@angle@ii\pgf@tmp@angle@ii
- \let\pgf@nfold@next@first\pgf@nfold@cur@last
- \def\pgf@nfold@next@supporta{\pgf@x#1\pgf@y#2}
- \def\pgf@nfold@next@supportb{\pgf@x#3\pgf@y#4}
- \def\pgf@nfold@next@last{\pgf@x#5\pgf@y#6}
- \pgf@nfold@parser@handlesegment%
-}%
-
-\def\pgf@nfold@parseclosepath#1#2{%
- \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
- % closepath segments should always be processed even if they have zero length
- \pgfpointtaxicabnorm\pgf@xa%
- \ifdim\pgf@xa<0.1pt\relax%
- \pgf@nfold@parse@closepath@zerolength{#1}{#2}%
- \else%
- \pgf@nfold@parse@line@common{#1}{#2}{o}%
- \fi%
-}%
-
-\def\pgf@nfold@parse@closepath@zerolength#1#2{%
- \pgf@nfold@parser@moveup%
- \let\pgf@nfold@next@type=z%
- \let\pgf@nfold@next@visible=1%
- % Set the start and end tangent to the tangent of the first segment
- \let\pgf@nfold@next@tang@i\pgf@nfold@connsubpath@tang@i
- \let\pgf@nfold@next@tang@ii\pgf@nfold@connsubpath@tang@i
- \let\pgf@nfold@next@angle@i\pgf@nfold@connsubpath@angle@i
- \let\pgf@nfold@next@angle@ii\pgf@nfold@connsubpath@angle@i
- \let\pgf@nfold@next@first\pgf@nfold@cur@last
- % If problems arise, we need to put a fake point here (like \pgf@nfold@next@first + \pgf@nfold@next@tang@i)
- \def\pgf@nfold@next@last{\pgf@x#1\pgf@y#2}%
- \pgf@nfold@parser@handlesegment%
-}
-
-\def\pgf@nfold@parseinvisibleline#1#2{%
- \pgf@process{\pgfpointdiff{\pgf@nfold@next@last}{\pgf@x#1\pgf@y#2}}%
- \pgfpointtaxicabnorm\pgf@xa%
- % In order to correctly render the start/end join in a closed path,
- % the \pgfpathclose segment is copied to the start of the path as an invisible line.
- % Counterintuitively, an "invisibleline" segment has next@visible=1 because
- % we want its end join to be rendered.
- % In case the \pgfpathclose segment has non-zero length, we can just use a copy of
- % this segment for the invisible line. Otherwise, the invisble line segment must will receive
- % the same angle/tangent as the last finite-sized segment, which is the second-to-last
- % segment overall (cached in \pgf@nfold@sectolast@segment).
- \ifdim\pgf@xa>.1pt\relax%
- \pgf@nfold@parse@line@common{#1}{#2}{i}%
- \else%
- \begingroup%
- % find the tangent of the second-to-last segment
- \let\pgf@nfold@parser@handlesegment\relax%
- \pgf@nfold@sectolast@segment%
- \global\let\pgf@nfold@tmp\pgf@nfold@next@tang@ii%
- \endgroup%
- % Construct an invisible line with length 1pt and the correct tangent.
- % This step might not be needed since the join computations only require the tangent,
- % but the invisibleline segment would be inconsistent otherwise, so better play it safe.
- \pgfextract@process\pgf@nfold@next@first{\pgfpointdiff{\pgf@nfold@tmp}{\pgfqpoint{#1}{#2}}}%
- % write the tangent into (\pgf@x, \pgf@y) where the next macro expects it to be
- \pgf@nfold@tmp%
- \pgf@nfold@parse@line@common{#1}{#2}{i}%
- \fi%
-}%
-
-\def\pgf@nfold@parselast{%
- \pgf@nfold@parser@moveup%
- \let\pgf@nfold@next@type=t%
- \let\pgf@nfold@next@visible=0%
- \pgf@nfold@parser@handlesegment%
-}
-
-% Mostly for the sake of completeness; using TikZ' "\path (0,0) rectangle (1,1);" does not call this code
-\def\pgf@nfold@parserect#1#2#3#4{%
- \pgf@nfold@parsemoveto{#1}{#2}%
- \pgf@xc=#1\relax
- \pgf@yc=#2\relax
- \pgf@xd=#3\relax
- \pgf@yd=#4\relax
- \advance\pgf@yc\pgf@yd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \advance\pgf@xc\pgf@xd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \advance\pgf@yc-\pgf@yd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \advance\pgf@xc-\pgf@xd%
- \edef\pgf@temp{{\the\pgf@xc}{\the\pgf@yc}}%
- \expandafter\pgf@nfold@parselineto\pgf@temp%
- \edef\pgf@marshal{\noexpand\pgf@nfold@parsemoveto{\the\pgf@xc}{\the\pgf@yc}}%
- \pgf@marshal%
-}
-
-% adds the contents of \pgf@nfold@macrotoadd to #1
-\def\pgf@nfold@addmacro#1{%
- % need a \gdef because we have nested groups in the subdivision
- \expandafter\expandafter\expandafter\gdef%
- \expandafter\expandafter\expandafter#1%
- \expandafter\expandafter\expandafter{%
- \expandafter#1\pgf@nfold@macrotoadd}%
-}
-
-
-%
-% Tokens for the parsed path
-%
-
-%#3: cached normalised tangent (for efficiency)
-\def\pgf@nfold@token@lineto#1#2#3{%
- \pgfoffsetline@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
-}
-
-\def\pgf@nfold@token@lineto@continue#1#2#3{%
- \pgfoffsetlinenomove@{#1}{#2}{\pgf@nfold@shiftamount}{#3}%
-}
-
-\def\pgf@nfold@token@invisibleline#1#2#3{%
- % An invisible line should execute a moveto to the end point of the line
- \pgfqpointscale{\pgf@nfold@shiftamount}{#3}%
- \pgf@xc=-\pgf@y%
- \pgf@y=\pgf@x%
- \pgf@x=\pgf@xc%
- \pgfpathmoveto{\pgfpointadd{}{#2}}%
-}
-
-% #5, #6: cached normalised tangents at start and end (for efficiency)
-\def\pgf@nfold@token@curveto#1#2#3#4#5#6{%
- \def\pgf@tmp@tang@i{#5}%
- \def\pgf@tmp@tang@ii{#6}%
- \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
- \pgfpathmoveto{\pgf@bezier@offset@i}%
- \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
-}
-
-\def\pgf@nfold@token@curveto@continue#1#2#3#4#5#6{%
- \def\pgf@tmp@tang@i{#5}%
- \def\pgf@tmp@tang@ii{#6}%
- \pgf@offset@bezier@segment@{#1}{#2}{#3}{#4}{\pgf@nfold@shiftamount}%
- \pgfpathcurveto{\pgf@bezier@offset@ii}{\pgf@bezier@offset@iii}{\pgf@bezier@offset@iv}%
-}
-
-\def\pgf@nfold@token@closepath{%
- \pgfpathclose%
-}
-
-% This is needed for some edge case explained above.
-% #1: segment@start, which is actually the end point of the current segment in the edge case
-% #2: the angle of the current segment (start or end does not matter for straight lines)
-\def\pgf@nfold@token@edgecase@movetostart#1#2{%
- \pgfpathmoveto{\pgfpointadd%
- {#1}{\pgfpointpolar{#2+90}{\pgf@nfold@shiftamount}}}%
-}
-
-
-\def\pgf@nfold@parse@setupfirst{%
- \let\pgf@nfold@next@type=f%
- % technically, @visible can be derived from @type, but I think this is more efficient
- \let\pgf@nfold@next@visible=0%
- \edef\pgf@nfold@next@last{\pgf@x\the\pgf@path@lastx\pgf@y\the\pgf@path@lasty}%
- % the following only need to be set if visible=1
- % TODO these are disabled temporarily; an attempt to read them suggests that there
- % is a bug, because their content has no meaning at this point. Consider reenabling
- % if compile errors show up, but if they do, the root of the problem is likely to be elsewhere
- %\let\pgf@nfold@next@tang@i=\pgfpointorigin%
- %\let\pgf@nfold@next@tang@ii=\pgfpointorigin%
- % \def\pgf@nfold@next@angle@i{0}%
- % \def\pgf@nfold@next@angle@ii{0}%
- % \let\pgf@nfold@next@first\pgfpointorigin%
- % the following only need to be set if type=c
- % \let\pgf@nfold@next@supporta\pgfpointorigin%
- % \let\pgf@nfold@next@supportb\pgfpointorigin%
-}
-
-\def\pgf@nfold@clampangle{
- % The computed angles are values between 0 and 360, so their difference is between 360 and -360;
- % we want the difference to be between -180 and 180
- \ifdim\pgfmathresult pt<-180pt\relax
- \pgfutil@tempdima=\pgfmathresult pt
- \advance\pgfutil@tempdima by 360pt
- \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
- \else\ifdim\pgfmathresult pt>180pt\relax
- \pgfutil@tempdima=\pgfmathresult pt
- \advance\pgfutil@tempdima by -360pt
- \edef\pgfmathresult{\pgf@sys@tonumber\pgfutil@tempdima}
- \fi\fi
-}
-
-
-
-\def\pgf@nfold@parser@moveup{%
- \let\pgf@nfold@prev@type\pgf@nfold@cur@type%
- \let\pgf@nfold@prev@visible\pgf@nfold@cur@visible%
- \let\pgf@nfold@prev@tang@i\pgf@nfold@cur@tang@i%
- \let\pgf@nfold@prev@tang@ii\pgf@nfold@cur@tang@ii%
- \let\pgf@nfold@prev@angle@i\pgf@nfold@cur@angle@i%
- \let\pgf@nfold@prev@angle@ii\pgf@nfold@cur@angle@ii%
- \let\pgf@nfold@prev@first\pgf@nfold@cur@first%
- \let\pgf@nfold@prev@supporta\pgf@nfold@cur@supporta%
- \let\pgf@nfold@prev@supportb\pgf@nfold@cur@supportb%
- \let\pgf@nfold@prev@last\pgf@nfold@cur@last%
- \let\pgf@nfold@cur@type\pgf@nfold@next@type%
- \let\pgf@nfold@cur@visible\pgf@nfold@next@visible%
- \let\pgf@nfold@cur@tang@i\pgf@nfold@next@tang@i%
- \let\pgf@nfold@cur@tang@ii\pgf@nfold@next@tang@ii%
- \let\pgf@nfold@cur@angle@i\pgf@nfold@next@angle@i%
- \let\pgf@nfold@cur@angle@ii\pgf@nfold@next@angle@ii
- \let\pgf@nfold@cur@first\pgf@nfold@next@first%
- \let\pgf@nfold@cur@supporta\pgf@nfold@next@supporta%
- \let\pgf@nfold@cur@supportb\pgf@nfold@next@supportb%
- \let\pgf@nfold@cur@last\pgf@nfold@next@last%
-}
-
-%
-% Iterating over the parsed soft path
-% -----------------------------------
-%
-
-\newcount\pgf@nfold@index
-\def\pgf@nfold@run@loop{%
- \pgf@nfold@index=\pgf@nfold@order%
- \pgf@nfold@run@loop@%
-}
-
-\def\pgf@nfold@run@loop@{%
- \pgf@nfold@loop@inner%
- \advance\pgf@nfold@index by -1\relax
- \ifnum\pgf@nfold@index>0\relax%
- \pgf@nfold@run@loop@%
- \fi%
-}
-
-\def\pgf@nfold@loop@inner{%
- \pgfmathsetmacro{\pgf@nfold@shift@fraction}%
- {-1+2*(\pgf@nfold@index-1)/(\pgf@nfold@order-1)}%
- % Do not store shiftamount as a length (i.e. with pt) because we want to use it in \pgfqpointscale{}{}
- \pgfmathsetmacro{\pgf@nfold@shiftamount}{\pgf@nfold@hwidth*\pgf@nfold@shift@fraction}
- % Transformations are already baked into the path; without this call, they would be applied twice
- \pgftransformreset%
- \parsedpath%
- \pgfsyssoftpath@flushcurrentpath%
- \pgf@up@action%
-}
-
-% Computes both the width of the component lines into \pgf@x and the distance
-% from the center to the outermost line centers into \pgf@y
-% from the current values of \pgflinewidth and \pgfinnerlinewidth.
-\def\pgf@nfold@compute@widths@from@double{
- \pgf@x=\pgflinewidth\relax%
- \pgf@y=\pgf@x\relax%
- \advance\pgf@x-\pgfinnerlinewidth\relax%
- \advance\pgf@y+\pgfinnerlinewidth\relax%
- \pgf@x=.5\pgf@x\relax%
- \pgf@y=.25\pgf@y\relax%
-}
-
-\def\pgf@nfold@render@cached@softpath{%
- \pgfscope% must use a scope, otherwise we break the arrow tips
- % Compute the full and constituent part line widths
- \pgf@nfold@compute@widths@from@double%
- \pgfsetlinewidth\pgf@x%
- \edef\pgf@nfold@hwidth{\the\pgf@y}%
- \pgfprocessround{\pgf@nfold@cachedpath}{\pgf@nfold@cachedpath}% remove tokens from the soft path
- \pgf@nfold@parsearrows%
- \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
- \pgf@nfold@run@loop%
- \endpgfscope%
-}
-
-
-%
-% user interface and pgf/TikZ keys
-% --------------------------------
-%
-
-% Outputs a provided soft path in #1 offset by a distance provided in #2.
-\def\pgfoffsetpath#1#2{%
- \begingroup
- \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
- % \pgf@nfold@hwidth must always be positive
- \pgf@x=\pgf@nfold@parsed@hwidth\relax
- \ifdim\pgf@x<0pt\relax
- \pgf@x=-\pgf@x
- \def\pgf@nfold@shift@fraction{-1}
- \else
- \def\pgf@nfold@shift@fraction{1}
- \fi
- \edef\pgf@nfold@parsed@hwidth{\the\pgf@x}
- \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
- \endgroup
-}
-
-% Outputs a provided soft path in #1 offset by #3*#2 where #2 is a length (>= 0 pt)
-% and #3 is a number between -1.0 and 1.0. This differs from \pgfoffsetpath{#1}{#2*#3}
-% in how the joins between segments are rendered. In particular, \pgfoffsetpathfraction{#1}{10pt}{0}
-% does *not* yield the original path, but a new path in the centre of #1 drawn at line width 20pt.
-%
-\def\pgfoffsetpathfraction#1#2#3{%
- \begingroup
- \pgfmathsetlengthmacro\pgf@nfold@parsed@hwidth{#2}
- \pgfmathsetmacro\pgf@nfold@shift@fraction{#3}
- \pgfoffsetpathqfraction{#1}{\pgf@nfold@parsed@hwidth}{\pgf@nfold@shift@fraction}
- \endgroup
-}
-
-% This has the same output as the #3-th segment of nfold=#4.
-\def\pgfoffsetpathindex#1#2#3#4{%
- \begingroup
- \pgfmathsetmacro\pgf@nfold@shift@fraction{-1+2*(#3-1)/(#4-1)}
- \pgfoffsetpathqfraction{#1}{#2}{\pgf@nfold@shift@fraction}
- \endgroup
-}
-
-% A quick version that skips processing the input values
-\def\pgfoffsetpathqfraction#1#2#3{%
- \begingroup
- \pgf@x=#2\relax
- \edef\pgf@nfold@hwidth{\the\pgf@x}
- \edef\pgf@nfold@shift@fraction{#3}
- \pgf@x=\pgf@nfold@shift@fraction\pgf@x\relax
- \edef\pgf@nfold@shiftamount{\pgf@sys@tonumber\pgf@x}
- \pgfprocessround{#1}{\pgf@nfold@cachedpath}% remove tokens from the soft path
- \pgf@nfold@parsesoftpath{\pgf@nfold@cachedpath}{\parsedpath}%
- % Transformations are already baked into the path; without this call, they would be applied twice
- \pgftransformreset%
- \parsedpath%
- \endgroup
-}
-
-
-\pgfkeys{
- /pgf/nfold/.code={%
- \pgf@nfold@order=#1\relax%
- \ifnum\pgf@nfold@order<1\relax%
- \pgfutil@packageerror{tikz-nfold}{The key /pgf/nfold must take a value of at least 1, got \the\pgf@nfold@order}{}%
- \fi%
- % If nfold > numcached AND intersections is not loaded AND we draw an Implies tip, we get an error.
- % We check the first two conditions now and set the respective flag
- \ifnum\pgf@nfold@order>\pgf@nfold@intersec@numcached\relax
- \ifdefined\pgfintersectionofpaths\else
- \pgf@nfold@intersectionsnotloadedtrue
- \fi
- \fi
- },
- /pgf/nfold/.default=2
-}
-
+\usepgflibrary{nfold}
+\usetikzlibrary{arrows.meta}
-% use \tikzset for scoping reasons, does not appear to be equivalent to \pgfset{/tikz/...=...}
\tikzset{
nfold/.code={
\edef\pgf@tmp{\noexpand\pgfkeys{/pgf/nfold=#1}}
- % patch \tikz@double@setup to set /pgf/nfold=#1 as well
\expandafter\expandafter\expandafter\def%
\expandafter\expandafter\expandafter\tikz@double@setup%
\expandafter\expandafter\expandafter{\expandafter\tikz@double@setup\pgf@tmp}
},
nfold/.default=2,
scaling nfold/.code={%
- \pgfscope% scope to contain \tikz@double@setup
+ \pgfscope%
\tikz@double@setup
- % extract double distance between line centers into \pgf@x
\pgf@nfold@compute@widths@from@double
\pgf@y=2\pgf@y
- % store (order-1)*\pgf@x in \pgf@xa
\c@pgf@counta=#1
\advance\c@pgf@counta by -1\relax
\global\pgf@y=\c@pgf@counta\pgf@y
@@ -1329,21 +47,16 @@
}
},
scaling nfold/.default=2,
- % This simply defines the key if tikzcd is not loaded, so we don't run into any errors
commutative diagrams/scaling nfold/.code={
- \pgfscope% scope to contain \tikz@double@setup
+ \pgfscope%
\tikz@double@setup
- % extract double distance between line centers into \pgf@x
\pgf@nfold@compute@widths@from@double
- % store (order-1)*\pgf@y in \pgf@ya
\c@pgf@counta=#1
\advance\c@pgf@counta by -1\relax
\pgf@ya=\c@pgf@counta\pgf@y
- % compute the label offset, which is (order-2)*\pgf@y + .5*\pgf@x
\advance\c@pgf@counta by -1\relax
\pgf@xa=\c@pgf@counta\pgf@y
\advance\pgf@xa by .5\pgf@x
- % save the results in \pgf@x and \pgf@y
\global\pgf@x=\pgf@xa
\global\pgf@y=2\pgf@ya
\endpgfscope
diff --git a/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.pdf b/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.pdf
index a6610abd58..68574d0bff 100644
--- a/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.pdf
+++ b/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.pdf
Binary files differ
diff --git a/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.tex b/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.tex
index 5793927f74..287d240690 100644
--- a/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.tex
+++ b/graphics/pgf/contrib/tikz3d-fr/doc/tikz3d-fr-doc.tex
@@ -4,8 +4,8 @@
\documentclass[french,a4paper,11pt]{article}
\usepackage[margin=2cm,includefoot]{geometry}
-\def\TPversion{0.1.1}
-\def\TPdate{24 Mai 2023}
+\def\TPversion{0.1.2}
+\def\TPdate{22 juillet 2023}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath,amssymb}
@@ -246,6 +246,8 @@
\part{Historique}
+\verb|v0.1.2|~:~~~~Option pour l'épaisseur des traits + \textsf{[line join=round]} pour les cubes
+
\verb|v0.1.1|~:~~~~Tracé des segments individuels avec l'option \textsf{[line cap=round]}
\verb|v0.1.0|~:~~~~Version initiale
@@ -592,7 +594,7 @@ Il existe également la commande \texttt{\textbackslash PlaqueVide} pour \textit
\begin{PresCodeTex}{listing only}
\begin{EmpilementCubes}[échelle]<options tikz>
- \PlaquePetitsCubes[couleur(s)]{empilement}
+ \PlaquePetitsCubes[couleur(s)]{empilement}[épaisseur traits]
\PlaqueVide[nb]
\end{EmpilementCubes}
\end{PresCodeTex}
@@ -619,6 +621,10 @@ Le second argument, obligatoire et entre \texttt{\{...\}} est quant à lui la li
\item un \texttt{-} code un \textit{trou}, et un numéro code une couleur (comme définie(s) précédemment).
\end{itemize}
+Le dernier argument, optionnel et entre \texttt{[...]} permet de spécifier une dimension pour les tracés (\texttt{0.2pt} par défaut).
+
+\medskip
+
Cette manière permet de créer des plaques avec couleurs \textit{individuelles} et des \textit{trous} éventuels.
\end{tipblock}
@@ -633,13 +639,13 @@ Cette manière permet de créer des plaques avec couleurs \textit{individuelles}
\begin{PresCode}{}
\begin{EmpilementCubes}
%plaque n°1 (fond)
- \PlaquePetitsCubes{ 1111 / 1111 }
+ \PlaquePetitsCubes{ 1111 / 1111 }[0.4pt]
\PlaqueVide[2]
%plaque n°2
- \PlaquePetitsCubes[cyan/red]{ 111- / -211 }
+ \PlaquePetitsCubes[cyan/red]{ 111- / -211 }[0.4pt]
\PlaqueVide[2]
%plaque n°3 (devant)
- \PlaquePetitsCubes{ 1111 / ---1 }
+ \PlaquePetitsCubes{ 1111 / ---1 }[0.4pt]
\end{EmpilementCubes}
\end{PresCode}
@@ -657,9 +663,9 @@ Cette manière permet de créer des plaques avec couleurs \textit{individuelles}
\begin{PresCode}{}
\begin{EmpilementCubes}[1.75]
- \PlaquePetitsCubes[cyan/red/green/yellow]{ 3111-1-4 / 233123 / 2-1112 }
- \PlaquePetitsCubes[cyan/red]{ 111 / -21 }
- \PlaquePetitsCubes[cyan/red/green]{ 3-2 }
+ \PlaquePetitsCubes[cyan/red/green/yellow]{ 3111-1-4 / 233123 / 2-1112 }[1pt]
+ \PlaquePetitsCubes[cyan/red]{ 111 / -21 }[1pt]
+ \PlaquePetitsCubes[cyan/red/green]{ 3-2 }[1pt]
\end{EmpilementCubes}
\end{PresCode}
@@ -678,13 +684,13 @@ La commande qui permet de réaliser cet empilement est \texttt{\textbackslash Bl
\begin{PresCodeTex}{listing only}
%création dans un environnement dédié
\begin{EmpilementCubes}[échelle]<options tikz>
- \BlocPetitsCubes*[couleur]{grille des hauteurs}
+ \BlocPetitsCubes*[couleur]{grille des hauteurs}[epaisseur traits]
\end{EmpilementCubes}
\end{PresCodeTex}
\begin{PresCodeTex}{listing only}
%création autonome
-\BlocPetitsCubes[couleur]{grille des hauteurs}
+\BlocPetitsCubes[couleur]{grille des hauteurs}[epaisseur traits]
\end{PresCodeTex}
\begin{cautionblock}
@@ -721,7 +727,8 @@ Le second argument, obligatoire et entre \texttt{\{...\}} est quant à lui la li
\item le caractère de séparation des \textit{plaques} est le \texttt{/} ;
\item pour chaque plaque, le caractère de séparation des colonnes est le \texttt{,}.
\end{itemize}
-\vspace*{-\baselineskip}\leavevmode
+
+Le dernier argument, optionnel et entre \texttt{[...]} permet de spécifier une dimension pour les tracés (\texttt{0.2pt} par défaut).
\end{tipblock}
\begin{importantblock}
@@ -747,7 +754,7 @@ Par exemple, la \textit{grille} associée à l'empilement précédent est :
\begin{PresCode}{}
\begin{EmpilementCubes}[2]
- \BlocPetitsCubes*[violet]{1,2,3,4,5 / 0,2,1,1,3 / 0,2,1,1,2 / 1,1,1,1,1}
+ \BlocPetitsCubes*[violet]{1,2,3,4,5 / 0,2,1,1,3 / 0,2,1,1,2 / 1,1,1,1,1}[0.8pt]
\end{EmpilementCubes}
\end{PresCode}
diff --git a/graphics/pgf/contrib/tikz3d-fr/tex/tikz3d-fr.sty b/graphics/pgf/contrib/tikz3d-fr/tex/tikz3d-fr.sty
index 6ee9118c66..5056c951a8 100644
--- a/graphics/pgf/contrib/tikz3d-fr/tex/tikz3d-fr.sty
+++ b/graphics/pgf/contrib/tikz3d-fr/tex/tikz3d-fr.sty
@@ -3,8 +3,9 @@
% or later, see http://www.latex-project.org/lppl.txtf
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{tikz3d-fr}[2023/05/24 0.1.1 Aide pour l'utilisation de TikZ 3D]
-%0.1.1 Segments avec line cap=round
+\ProvidesPackage{tikz3d-fr}[2023/07/22 0.1.2 Aide pour l'utilisation de TikZ 3D]
+%0.1.2 Option pour l'épaisseur des traits + [line join=round] pour les cubes
+%0.1.1 Segments avec [line cap=round]
%0.1.0 Version initiale
%------Packages utiles
@@ -255,18 +256,18 @@
\end{tikzpicture}
}
-\NewDocumentCommand\PetitCube{ O{cyan} m }{%
- \StrBefore[1]{#2}{,}[\xtmp]%
- \StrBetween[1,2]{#2}{,}{,}[\ytmp]%
- \StrBehind[2]{#2}{,}[\ztmp]%
- \draw[fill=#1!70,very thin,line join=bevel] ({\xtmp+1},\ytmp,\ztmp)--++(0,1,0)--++(0,0,-1)--++(0,-1,0)--cycle;
- \draw[fill=#1!80,very thin,line join=bevel] (\xtmp,{\ytmp+1},\ztmp)--++(1,0,0)--++(0,0,-1)--++(-1,0,0)--cycle;
- \draw[fill=#1!35!white,very thin,line join=bevel] (\xtmp,\ytmp,\ztmp)--++(1,0,0)--++(0,1,0)--++(-1,0,0)--cycle;
+\NewDocumentCommand\PetitCube{ O{cyan} O{0.2pt} m }{%
+ \StrBefore[1]{#3}{,}[\xtmp]%
+ \StrBetween[1,2]{#3}{,}{,}[\ytmp]%
+ \StrBehind[2]{#3}{,}[\ztmp]%
+ \draw[fill=#1!70,line width=#2,line join=round,line cap=round] ({\xtmp+1},\ytmp,\ztmp)--++(0,1,0)--++(0,0,-1)--++(0,-1,0)--cycle;
+ \draw[fill=#1!80,line width=#2,line join=round,line cap=round] (\xtmp,{\ytmp+1},\ztmp)--++(1,0,0)--++(0,0,-1)--++(-1,0,0)--cycle;
+ \draw[fill=#1!35!white,line width=#2,line join=round,line cap=round] (\xtmp,\ytmp,\ztmp)--++(1,0,0)--++(0,1,0)--++(-1,0,0)--cycle;
}
\newcounter{lgblocs}%compteur des lignes, qui sera incrémenté
\NewDocumentCommand\PlaqueVide{ O{1} }{\addtocounter{lgblocs}{#1}}%passer une plaque
-\NewDocumentCommand\PlaquePetitsCubes{ O{cyan} m }{%poser un cube (attention à l'ordre)
+\NewDocumentCommand\PlaquePetitsCubes{ O{cyan} m O{0.2pt} }{%poser un cube (attention à l'ordre)
\setsepchar[.]{/}
%lecture des couleurs
\readlist*\ListeCouleurs{#1}
@@ -288,13 +289,13 @@
{}%
{%
\itemtomacro\ListeCouleurs[\elementtmp]{\elementcouleur}
- \PetitCube[\elementcouleur]{-\j,\y,\i}
+ \PetitCube[\elementcouleur][#3]{-\j,\y,\i}
}%
}%
}%
}
-\NewDocumentCommand\BlocPetitsCubes{ s O{cyan} m }{%
+\NewDocumentCommand\BlocPetitsCubes{ s O{cyan} m O{0.2pt} }{%
%*pour autonome
%2=couleur unique
%3=liste des hauteurs (attention à l'ordre)
@@ -318,7 +319,7 @@
\xintifboolexpr{\Hauteur == 0}%
{}%
{%
- \foreach \z in {1,...,\Hauteur}{\PetitCube[#2]{-\x,\y,\z}}
+ \foreach \z in {1,...,\Hauteur}{\PetitCube[#2][#4]{-\x,\y,\z}}
}%
}%
}%