%% file: tzplot.sty
%%
%% tzplot
%%
%% (C) Copyright 2017-2022 In-Sung Cho <ischo at ktug.org>
%%
%% 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.
%%
%% -------------------------------------------------
\ProvidesPackage{tzplot}[2022/09/28 v2.1 Plot Graphs with TikZ Abbreviations]

% expl3,xparse: LPPL
% tikz: LPPL and/or GNU GPL
\RequirePackage{expl3,xparse}
\RequirePackage{tikz}

\usetikzlibrary{
arrows, % (deprecated in tikz)
backgrounds,
calc,
decorations.pathreplacing, % for tzshowcontrols, tzbrace
calligraphy, % for calligraphic brace (load after decorations.pathreplacing)
intersections,
patterns,
plotmarks, % for \tzplot[mark]
positioning,
shapes,
}

%%(ADDED)
\usetikzlibrary{
% for later use
%angles, % for \tzpicangle   %% (Removed!!!)
arrows.meta, % (added)
bending,     % (added with arrows.meta)
decorations.markings, % need for "decoration"
decorations.pathmorphing, % for \tzsnake
spy,  % for \tzspy (later)
fpu,  % for computation for \tzpicangle
%fit,
%quotes,
%through,
%shadings,
%shadows,
%scopes,
%graphs,
}


%% backgrounds
\pgfdeclarelayer{background}
\pgfdeclarelayer{behind}
\pgfdeclarelayer{above}
\pgfdeclarelayer{foreground}

\pgfsetlayers{background,behind,main,above,foreground}
%% USAGE: \begin{pgfonlayer}{foreground} ... \end{pgfonlayer}


%%%%% defaults

%%%%% basic defaults

%% circle dot (using radius)
\def\tz@default@Cdot@radius{1.2pt}                     % fixed
\def\tz@initial@Cdot@radius{\tz@default@Cdot@radius}   % changeable
\NewDocumentCommand\settzcdotradius{m}{\renewcommand\tz@initial@Cdot@radius{#1}}
\newcommand\tzCdotradius{\tz@initial@Cdot@radius}

%% node dot (using minimum size: diameter)
\def\tz@default@dot@size{2.4pt}                        % fixed
\def\tz@initial@dot@size{\tz@default@dot@size}         % changeable
\NewDocumentCommand\settzdotsize{m}{\renewcommand\tz@initial@dot@size{#1}}
\newcommand\tzdotsize{\tz@initial@dot@size}

%% mark (using mark size: radius)            % tikz initial = 2pt
\def\tz@default@mark@size{2pt}                         % fixed
\def\tz@initial@mark@size{\tz@default@mark@size}       % changeable
\NewDocumentCommand\settzmarksize{m}{\renewcommand\tz@initial@mark@size{#1}}
\newcommand\tzmarksize{\tz@initial@mark@size}

%% opacity
\def\tz@default@fill@opacity{0.3}                      % fixed
\def\tz@initial@fill@opacity{\tz@default@fill@opacity} % changeable
\NewDocumentCommand\settzfillopacity{m}{\renewcommand\tz@initial@fill@opacity{#1}}
\newcommand\tzfillopacity{\tz@initial@fill@opacity}

%% fillcolor
\def\tz@default@fill@color{black!50}                   % fixed
\def\tz@initial@fill@color{\tz@default@fill@color}     % changeable
\NewDocumentCommand\settzfillcolor{mg}
{%
 \renewcommand\tz@initial@fill@color{#1}
 \IfValueT {#2} {\renewcommand\tz@initial@fill@opacity{#2}}
}
\newcommand\tzfillcolor{\tz@initial@fill@color}

%% link style
\def\tz@default@link@style{to}                         % fixed
\def\tz@initial@link@style{\tz@default@link@style}     % changeable
\NewDocumentCommand\settzlinkstyle{m}{\renewcommand\tz@initial@link@style{#1}}
\newcommand\tzlinkstyle{\tz@initial@link@style}

\let\tzpathstyle\tzlinkstyle
\let\settzpathstyle\settzlinkstyle

%%% path style
%\def\tz@default@path@style{to}                         % fixed
%\def\tz@initial@path@style{\tz@default@path@style}     % changeable
%\NewDocumentCommand\settzpathstyle{m}{\renewcommand\tz@initial@path@style{#1}}
%\newcommand\tzpathstyle{\tz@initial@path@style}

%% tangent epsilon

\def\tz@default@tangent@epsilonL{.01}
\def\tz@default@tangent@epsilonR{.01}
\def\tz@initial@tangent@epsilonL{\tz@default@tangent@epsilonL}
\def\tz@initial@tangent@epsilonR{\tz@default@tangent@epsilonL}
\NewDocumentCommand\settztangentepsilon{mg}
{%
 \renewcommand\tz@initial@tangent@epsilonL{#1}
 \IfNoValueTF {#2}
 {\renewcommand\tz@initial@tangent@epsilonR{#1}}
 {\renewcommand\tz@initial@tangent@epsilonR{#2}}
}
\newcommand\tztangentepsilonL{\tz@initial@tangent@epsilonL}
\newcommand\tztangentepsilonR{\tz@initial@tangent@epsilonR}

\let\tztangentatepsilonL\tztangentepsilonL
\let\tztangentatepsilonR\tztangentepsilonR

%%(ADDED)
%% slope epsilon

\def\tz@default@slope@epsilonL{.01}
\def\tz@default@slope@epsilonR{.01}
\def\tz@initial@slope@epsilonL{\tz@default@slope@epsilonL}
\def\tz@initial@slope@epsilonR{\tz@default@slope@epsilonL}
\NewDocumentCommand\settzslopeepsilon{mg}
{%
 \renewcommand\tz@initial@slope@epsilonL{#1}
 \IfNoValueTF {#2}
 {\renewcommand\tz@initial@slope@epsilonR{#1}}
 {\renewcommand\tz@initial@slope@epsilonR{#2}}
}
\newcommand\tzslopeepsilonL{\tz@initial@slope@epsilonL}
\newcommand\tzslopeepsilonR{\tz@initial@slope@epsilonR}

\let\tzslopeatepsilonL\tzslopeepsilonL
\let\tzslopeatepsilonR\tzslopeepsilonR


%% normal epsilon

\def\tz@default@normal@epsilonL{.01}
\def\tz@default@normal@epsilonR{.01}
\def\tz@initial@normal@epsilonL{\tz@default@normal@epsilonL}
\def\tz@initial@normal@epsilonR{\tz@default@normal@epsilonL}
\NewDocumentCommand\settznormalepsilon{mg}
{%
 \renewcommand\tz@initial@normal@epsilonL{#1}
 \IfNoValueTF {#2}
 {\renewcommand\tz@initial@normal@epsilonR{#1}}
 {\renewcommand\tz@initial@normal@epsilonR{#2}}
}
\newcommand\tznormalepsilonL{\tz@initial@normal@epsilonL}
\newcommand\tznormalepsilonR{\tz@initial@normal@epsilonR}

\let\tznormalatepsilonL\tznormalepsilonL
\let\tznormalatepsilonR\tznormalepsilonR


%%%%% layers: defaults

%% tzpath layer %% default: main
\def\tz@default@tzpath@layer{main}                       % fixed
\def\tz@initial@tzpath@layer{\tz@default@tzpath@layer}   % changeable
\NewDocumentCommand\settzpathlayer{m}
 {\renewcommand\tz@initial@tzpath@layer{#1}}
\newcommand\tzpathlayer{\tz@initial@tzpath@layer}
%% (there is No \tz-link-layer thing)

%% tzfnArea layer %% default: main
\def\tz@default@tzfnArea@layer{behind}                     % fixed
\def\tz@initial@tzfnArea@layer{\tz@default@tzfnArea@layer} % changeable
\NewDocumentCommand\settzfnArealayer{m}
 {\renewcommand\tz@initial@tzfnArea@layer{#1}}
\newcommand\tzfnArealayer{\tz@initial@tzfnArea@layer}

%% tzfnarea layer %% default: main
\def\tz@default@tzfnarea@layer{behind}                     % fixed
\def\tz@initial@tzfnarea@layer{\tz@default@tzfnarea@layer} % changeable
\NewDocumentCommand\settzfnarealayer{m}
 {\renewcommand\tz@initial@tzfnarea@layer{#1}}
\newcommand\tzfnarealayer{\tz@initial@tzfnarea@layer}

%% tangent layer
\def\tz@default@tangent@layer{behind}                    % fixed
\def\tz@initial@tangent@layer{\tz@default@tangent@layer} % changeable
\NewDocumentCommand\settztangentlayer{m}
 {\renewcommand\tz@initial@tangent@layer{#1}}
\newcommand\tztangentlayer{\tz@initial@tangent@layer}

\let\tztangentatlayer\tztangentlayer
\let\settztangentatlayer\settztangentlayer

%% secant layer
\def\tz@default@secant@layer{behind}                     % fixed
\def\tz@initial@secant@layer{\tz@default@secant@layer}   % changeable
\NewDocumentCommand\settzsecantlayer{m}
 {\renewcommand\tz@initial@secant@layer{#1}}
\newcommand\tzsecantlayer{\tz@initial@secant@layer}

\let\tzsecantatlayer\tzsecantlayer
\let\settzsecantatlayer\settzsecantlayer

%%(ADDED)
%% slope layer
\def\tz@default@slope@layer{behind}                      % fixed
\def\tz@initial@slope@layer{\tz@default@slope@layer}     % changeable
\NewDocumentCommand\settzslopelayer{m}
 {\renewcommand\tz@initial@slope@layer{#1}}
\newcommand\tzslopelayer{\tz@initial@slope@layer}

\let\tzslopeatlayer\tzslopelayer
\let\settzslopeatlayer\settzslopelayer

%% normal layer
\def\tz@default@normal@layer{behind}                     % fixed
\def\tz@initial@normal@layer{\tz@default@normal@layer}   % changeable
\NewDocumentCommand\settznormallayer{m}
 {\renewcommand\tz@initial@normal@layer{#1}}
\newcommand\tznormallayer{\tz@initial@normal@layer}

\let\tznormalatlayer\tznormallayer
\let\settznormalatlayer\settznormallayer

%% angle layer
\def\tz@default@angle@layer{behind}                      % fixed
\def\tz@initial@angle@layer{\tz@default@angle@layer}     % changeable
\NewDocumentCommand\settzanglelayer{m}
 {\renewcommand\tz@initial@angle@layer{#1}}
\newcommand\tzanglelayer{\tz@initial@angle@layer}

\let\tzanglemarklayer\tzanglelayer
\let\settzanglemarklayer\settzanglelayer


%%%%% line style, radius, size: defaults

%% function area (fnA) line width
\def\tz@default@fnA@linestyle{very thin}                   % fixed
\def\tz@initial@fnA@linestyle{\tz@default@fnA@linestyle} % changeable
\NewDocumentCommand\settzfnarealinestyle{m}
 {\renewcommand\tz@initial@fnA@linestyle{#1}}
\newcommand\tzfnALstyle{\tz@initial@fnA@linestyle}

%% angle arc (AA) line style
\def\tz@default@AA@linestyle{very thin}                   % fixed
\def\tz@initial@AA@linestyle{\tz@default@AA@linestyle} % changeable
\NewDocumentCommand\settzAAlinestyle{m}
 {\renewcommand\tz@initial@AA@linestyle{#1}}
\newcommand\tzAAlinestyle{\tz@initial@AA@linestyle}

\let\tzRAlinestyle\tzAAlinestyle
\let\settzRAlinestyle\settzAAlinestyle

%% angle arc (AA) radius
\def\tz@default@AA@radius{10pt}                              % fixed
\def\tz@initial@AA@radius{\tz@default@AA@radius}             % changeable
\NewDocumentCommand\settzAAradius{m}
 {\renewcommand\tz@initial@AA@radius{#1}}
\newcommand\tzAAradius{\tz@initial@AA@radius}

%% right angle (RA) marc size
\def\tz@default@RA@size{5pt}                                 % fixed
\xdef\tz@initial@RA@size{\tz@default@RA@size}                 % changeable
\NewDocumentCommand\settzRAsize{m}
 {\renewcommand\tz@initial@RA@size{#1}}
\newcommand\tzRAsize{\tz@initial@RA@size}


%%%%% TikZ alias styles

\tikzset{
 a/.style={above=#1},
 b/.style={below=#1},
 c/.style={centered=#1},
 l/.style={left=#1},
 r/.style={right=#1},
 al/.style={above left=#1},
 ar/.style={above right=#1},
 bl/.style={below left=#1},
 br/.style={below right=#1},
}

%%%%% tzplot styles

\tikzset{>=stealth} % to revert use {>=to}

%% tzdot (for node dot style)
\tikzset{
 tzdot/.style=
   {draw,solid,thin,circle,inner sep=0pt,minimum size=#1},
 tzdot/.default=\tzdotsize
}

%% tzdot options (for node dot style)
\tikzset{
 tzdot options/.style={tzdot=\tzdotsize,#1}
}

%%%%%%% tzshowdot
%%%%%\tikzset{
%%%%%  tzshowdot/.style=
%%%%%    {draw,fill,solid,thin,circle,inner sep=0pt,minimum size=\tzdotsize,#1},
%%%%%%  tzshowdot/.default=circle
%%%%%}

%% tzmark
\tikzset{
 tzmark/.style=
   {mark options={solid,thin},mark size=#1},
 tzmark/.default=\tzmarksize
}

%% tznode (NOT USED!) -- user choice
\tikzset{
 tznode/.style=
   {solid,thin,circle,inner sep=0pt,minimum size=#1},
 tznode/.default=0pt
}

%% tzdotted
\tikzset{%
 tzdotted/.style={%
   dotted=none,
   line cap=round,
   dash pattern=on 0pt off 1cm/(#1)
 },
 tzdotted/.default=10
}

%% tzdashed
\tikzset{
 tzdashed/.style={%
   dashed=none,
   dash pattern=on 5mm/(#1) off 5mm/(#1)
 },
 tzdashed/.default=10
}

%% tzhelplines
\tikzset{%
 tzhelplines/.style={help lines,-,tzdotted}
}

%% tzshorten
\tikzset{%
 tzshorten/.style 2 args ={shorten <=#1, shorten >=#2},
 tzshoretn/.default={2pt}{2pt}
}

%% tzextend (negative tzshorten)
\tikzset{%
 tzextend/.style 2 args ={shorten <=-#1, shorten >=-#2},
 tzextend/.default={2pt}{2pt}
}


%% tzshowcontrols  % (for \tzbezier: tikz manual p.645)
\tikzset{%
 tzshowcontrols/.style={%
   postaction={%
     decoration={%
       show path construction,
       curveto code={%
         \draw [dotted,#1]
               (\tikzinputsegmentfirst)
            -- (\tikzinputsegmentsupporta)
            -- (\tikzinputsegmentsupportb)
            -- (\tikzinputsegmentlast);
       }
     },
     decorate
   }
 }
}


%=====================================================
%%=====================================================
%%=====================================================
\ExplSyntaxOn
%%=====================================================
%%=====================================================

%%% error messages:

%% semicolon versions
\msg_new:nnn { tzplot } { semicolon-error }
            { You~may~have~forgotten~a~semicolon~here~or~above! }

%% infinite slope error: LFn related macros
\msg_new:nnn { tzplot } { infinite~slope~error }
            { Perhaps~you~are~trying~an~'infinite~slope'~here~or~above! }


%%%% string replacement
%%%%%% to use string replacement for label positions
\cs_new:Npn \extract_posopt:w [ #1 ] #2 \q_stop  % ndh
{
       \tl_set:Nn \l_label_pos_str_tl { [ \exp_not:n { #1 } ] } % \exp_not needed!!!

       \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #2 } }

   \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
   {
     {l} { \tl_put_right:Nn \l_label_pos_str_tl {left} }
     {r} { \tl_put_right:Nn \l_label_pos_str_tl {right} }
     {a} { \tl_put_right:Nn \l_label_pos_str_tl {above} }
     {b} { \tl_put_right:Nn \l_label_pos_str_tl {below} }
     {c} { \tl_put_right:Nn \l_label_pos_str_tl {center} }
     {al} { \tl_put_right:Nn \l_label_pos_str_tl {above~left} }
     {ar} { \tl_put_right:Nn \l_label_pos_str_tl {above~right} }
     {bl} { \tl_put_right:Nn \l_label_pos_str_tl {below~left} }
     {br} { \tl_put_right:Nn \l_label_pos_str_tl {below~right} }
       }
       {
               \tl_put_right:Nn \l_label_pos_str_tl { #2 }
       }
}


%%%%% help lines
\NewDocumentCommand\tzhelplines{ s O{} r() d() }
{
 \IfBooleanTF { #1 }
 {
   \IfNoValueTF { #4 }
   { \draw [ tzhelplines , use~as~bounding~box , #2 ] (0,0) grid (#3); }
   { \draw [ tzhelplines , use~as~bounding~box , #2 ] (#3)  grid (#4); }
 }
 {
   \IfNoValueTF { #4 }
   { \draw [ tzhelplines , #2 ] (0,0) grid (#3); }
   { \draw [ tzhelplines , #2 ] (#3)  grid (#4); }
 }
}


%%%%% \tzbbox
\NewDocumentCommand\tzbbox{ r() d() }
{
 \IfNoValueTF { #2 }
 {
   \useasboundingbox (0,0) rectangle (#1);
 }
 {
   \useasboundingbox (#1)  rectangle (#2);
 }
}

%%%%% \tzgetxyval
\NewDocumentCommand\tzgetxyval{ r() m m }
{
 \tikz@scan@one@point\pgfutil@firstofone(#1)\relax%
 \pgfmathparse{\the\pgf@x/28.45274}% convert pt to cm
 \edef#2{\pgfmathresult}%
 \pgfmathparse{\the\pgf@y/28.45274}% convert pt to cm
 \edef#3{\pgfmathresult}%
}

%%%%% (ADDED 2022/04/23)
%%%%% \tzpointlength
\NewDocumentCommand\tzdistance{ r() r() m g g }
{
 \tikz@scan@one@point\pgfutil@firstofone($(#2)-(#1)$)\relax%
 \pgfmathparse{veclen(\the\pgf@x,\the\pgf@y)/28.45274}% convert pt to cm
 \edef#3{\pgfmathresult}%
 \IfValueT { #4 } { \pgfmathparse{\the\pgf@x/28.45274}\edef#4{\pgfmathresult} }
 \IfValueT { #5 } { \pgfmathparse{\the\pgf@y/28.45274}\edef#5{\pgfmathresult} }
}

%%% NOT working correctly
%  { \pgfmathparse{round(veclen(\the\pgf@x,\the\pgf@y)/28.45274}*1000)/1000 }% rounded


%%% --- end of \tzgetxyval

%%%%%% \tzgetxyval (experimental)
%%%%%% seems not working
%\NewDocumentCommand\tzgetxyval{ g r() m m }
%{
%  \IfNoValueTF { #1 }
%  {
%    \def\tzptToDim{28.45274} % cm: default
%  }
%  {
%    \str_case:nnTF { #1 }
%    {
%      {pt} { \def\tzptToDim{1} }
%      {mm} { \def\tzptToDim{2.845274} }
%      {cm} { \def\tzptToDim{28.45274} }
%      {bp} { \def\tzptToDim{1.00374} }
%      {dd} { \def\tzptToDim{1.07} }
%      {pc} { \def\tzptToDim{12} }
%      {in} { \def\tzptToDim{72.26999} }
%    }
%    {
%      \def\tzptToDim{1} % default unit in tikz
%    }
%  }
%  \tikz@scan@one@point\pgfutil@firstofone(#2)\relax%
%  \pgfmathparse{\the\pgf@x/\tzptToDim}% convert pt to dim
%  \edef#3{\pgfmathresult}%
%  \pgfmathparse{\the\pgf@y/\tzptToDim}% convert pt to dim
%  \edef#4{\pgfmathresult}%
%}
%
%%%% --- end of \tzgetxyval





%%%%% Dots

%%% Node Dots %%% (basic: using minimum size)

%%% \tzdot
%%% *[opt]<shift>(coor){text}[pos,opt](size)

\bool_new:N \l_tzdot_shift_coor_bool

%%% \tzdot (main)
\NewDocumentCommand\tzdot
 { s O{} d<> r() +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzdot_cmd_tl

 \tl_if_empty:nF { #7 }
 { \renewcommand\tzdotsize{ #7 } }

%%%%%% to use string replacement for label positions
 \IfValueTF { #6 }
 {
       \tl_if_in:nnTF { #6 } { [ }
   { \extract_posopt:w #6 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #6 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #6 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzdot_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzdot_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzdot_shift_coor_tl
   \bool_set_false:N \l_tzdot_shift_coor_bool
 }

 \bool_if:NTF \l_tzdot_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzdot_cmd_tl
   {
     ( [ shift = { (\l_tzdot_shift_coor_tl) } ] #4 )
   }
 }
 { \tl_put_right:Nn \l_tzdot_cmd_tl { (#4) } }

 \tl_put_right:Nn \l_tzdot_cmd_tl { node } %%

 \IfBooleanTF { #1 }
 {
   \tl_put_right:Nn \l_tzdot_cmd_tl
     { [ tzdot , fill , }
 }
 {
   \tl_put_right:Nn \l_tzdot_cmd_tl
     { [ tzdot , }
 }
 \tl_put_right:Nx \l_tzdot_cmd_tl
   {
     label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #5 } } , % pos_str
   }
 \tl_put_right:Nn \l_tzdot_cmd_tl
   {
     minimum~size = \tzdotsize , #2 ] {}
   }
 \exp_last_unbraced:Nf \path \l_tzdot_cmd_tl ;
}

%%% --- end of \tzdot



%%% multiple dots
%%% coding CAUTION! : _tzdot_ changed to _tzdots_

%%% \tzdots
%%% repeat pattern: (coor){label}[pos]

\tl_new:N \l_tzdots_opt_tl
\tl_new:N \l_tzdots_cmd_tl
\bool_new:N \l_tzdots_shift_coor_bool

%%% \tzdots (main)
\NewDocumentCommand\tzdots{ s O{} d<> }
{
 \tl_clear:N \l_tzdots_cmd_tl

 \IfBooleanTF { #1 }
 { \tl_set:Nn \l_tzdots_STYLE_fill_tl { fill } }
 { \tl_set:Nn \l_tzdots_STYLE_fill_tl { fill = none } }

 \tl_if_empty:nTF { #2 }
 { \tl_set:Nn \l_tzdots_opt_tl { tzdot } }
 { \tl_set:Nn \l_tzdots_opt_tl { tzdot , #2 } }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzdots_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzdots_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzdots_shift_coor_tl
   \bool_set_false:N \l_tzdots_shift_coor_bool
 }

 \tzdots_check_token:n
}

\cs_new:Npn \tzdots_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzdots_sub_fn #1 }
%  { \tzdots_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzdots_sub_fn #1 }
   { ; } { \tzdots_late_opt_fn }
 }
 {
%    \tzdots_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}


\NewDocumentCommand\tzdots_sub_fn { r() +G{} >{\TrimSpaces}o }
{
%%%%%% to use string replacement for label positions
 \IfValueTF { #3 }
 {
       \tl_if_in:nnTF { #3 } { [ }
   { \extract_posopt:w #3 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #3 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #3 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \bool_if:NTF \l_tzdots_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzdots_cmd_tl
   {% if shift
     ( [ shift = { (\l_tzdots_shift_coor_tl) } ] #1 )
   }
 }
 { \tl_put_right:Nn \l_tzdots_cmd_tl { (#1) } }

 \tl_put_right:Nn \l_tzdots_cmd_tl { node } %%

 \tl_put_right:Nx \l_tzdots_cmd_tl
 {
   [
     \l_tzdots_STYLE_fill_tl ,
     minimum~size = \exp_not:n { \tzdotsize } ,
     label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #2 } } , % pos_str
 }
 \tl_put_right:No \l_tzdots_cmd_tl   % expand `once'
 {
     \l_tzdots_opt_tl
   ] {}
 }
 \tzdots_check_token:n
}

\NewDocumentCommand\tzdots_late_opt_fn { D(){\tz@initial@dot@size} }
{
 \renewcommand\tzdotsize{ #1 }

 \tzdots_stop_action
}


\NewDocumentCommand\tzdots_stop_action {}
{
 \exp_last_unbraced:Nf \path \l_tzdots_cmd_tl ;
}

%%% --- end of \tzdots


%%%%% Circle Dots -- (code original, using radius)

\keys_define:nn { keytzCdot }
{
 tzcdot  .tl_set:N = \key_tzCdot_radius_tl
}


%% (keep)
%% \tzcdot --- circle dot (original)
%%% *[<opt>]<shift>(coor){label}[angle](radius)

\clist_new:N \l_tzCdot_opt_clist
\bool_new:N \l_tzCdot_shift_coor_bool

%%% \tzcdot (main)
\NewDocumentCommand\tzcdot{ s o d<> r() +G{} >{\TrimSpaces}o d() }
{
 \tl_clear:N \l_tzCdot_opt_tl % (needed)
 \tl_clear:N \l_tzCdot_cmd_tl

 \renewcommand\tzCdotradius{\tz@initial@Cdot@radius}

 \IfValueT { #7 }
   { \renewcommand\tzCdotradius{ #7 } }

 \IfBooleanTF { #1 }
 { \tl_set:Nn \l_tzCdot_fill_tl { fill , solid, thin } }
 { \tl_set:Nn \l_tzCdot_fill_tl { solid , thin } }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzCdot_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzCdot_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzCdot_shift_coor_tl
   \bool_set_false:N \l_tzCdot_shift_coor_bool
 }

 \IfNoValueTF { #2 }
 {
   \tl_clear:N \l_tzCdot_opt_tl           % arg specifier O{}
 }
 {
    \clist_clear:N \l_tzCdot_opt_tested_clist
    \clist_set:Nn \l_tzCdot_opt_input_clist { #2 }
    \clist_map_inline:Nn \l_tzCdot_opt_input_clist
    {
      \str_if_in:nnTF { ##1 } { tzcdot }
      { % (matched item)
        \clist_pop:NN \l_tzCdot_opt_input_clist \l_label_pos_str_tl
        \keys_set:nV { keytzCdot } \l_label_pos_str_tl   % form: { tzcdot=\l_label_pos_str_tl }
        \exp_args:NNo \renewcommand\tzCdotradius { \key_tzCdot_radius_tl }
        \clist_map_break:
        % non-tested list remains
      }
      { % (tested items -> list)
        \clist_pop:NN \l_tzCdot_opt_input_clist \l_tmpb_tl
        \clist_put_right:NV \l_tzCdot_opt_tested_clist \l_tmpb_tl
      }
    }
    \clist_concat:NNN \l_tzCdot_opt_clist
                      \l_tzCdot_opt_tested_clist % tested list
                      \l_tzCdot_opt_input_clist  % remained list
    \clist_if_empty:NF \l_tzCdot_opt_clist
    { % expand x needed
      \tl_set:Nx \l_tzCdot_opt_tl { \clist_use:Nn \l_tzCdot_opt_clist {,} }
    }
 }

 \tl_put_right:Nx \l_tzCdot_cmd_tl
   {
     [ \l_tzCdot_fill_tl ,
   }
 \tl_put_right:No \l_tzCdot_cmd_tl  % expand `once'
   {
       \l_tzCdot_opt_tl
     ]
   }
 \bool_if:NTF \l_tzCdot_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzCdot_cmd_tl
     {
       ( [ shift = { (\l_tzCdot_shift_coor_tl) } ]#4 )
     }
 }
 { \tl_put_right:Nn \l_tzCdot_cmd_tl { ( #4 ) } } % no shift (normal)

 \tl_put_right:Nn \l_tzCdot_cmd_tl
   {
     circle ( \tzCdotradius )
   }
%%%%%% to use string replacement for label positions
 \IfValueTF { #6 }
 {
       \tl_if_in:nnTF { #6 } { [ }
   { \extract_posopt:w #6 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #6 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #6 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \tl_put_right:Nx \l_tzCdot_cmd_tl
   {
     node
       [ inner~sep = 0pt ,
         label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #5 } } % pos_str
       ] {}
   }
 \exp_last_unbraced:No \draw \l_tzCdot_cmd_tl ;
}

%%% --- end of \tzcdot


%%% multiple dots
%%% coding CAUTION! : _tzCdot_ changes to _tzCdots


%%% \tzcdots
%%% *[<opt>]<shift> (){}[] (){}[] repeated (){}[] ; (radius)
%%% repeat pattern: (coor){label}[angle]

\clist_new:N \l_tzCdots_opt_clist
\bool_new:N \l_tzCdots_size_call_bool
\bool_new:N \l_tzCdots_shift_coor_bool

%%% \tzcdots (main)
\NewDocumentCommand\tzcdots{ s o d<> }
{
 \renewcommand\tzCdotradius{\tz@initial@Cdot@radius}

 \tl_clear:N \l_tzCdots_opt_tl  % (needed)
 \tl_clear:N \l_tzCdots_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzCdots_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzCdots_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzCdots_shift_coor_tl
   \bool_set_false:N \l_tzCdots_shift_coor_bool
 }

 \IfNoValueTF { #2 }
 {
   \tl_clear:N \l_tzCdots_opt_tl              % arg specifier O{}
 }
 {
    \clist_clear:N \l_tzCdots_opt_tested_clist
    \clist_set:Nn \l_tzCdots_opt_input_clist { #2 }
    \clist_map_inline:Nn \l_tzCdots_opt_input_clist
    {
      \str_if_in:nnTF { ##1 } { tzcdot }
      {
        \clist_pop:NN \l_tzCdots_opt_input_clist \l_label_pos_str_tl
        \keys_set:nV { keytzCdot } \l_label_pos_str_tl
        \exp_args:NNo \renewcommand\tzCdotradius { \key_tzCdot_radius_tl }
        \bool_set_true:N \l_tzCdots_size_call_bool
        \clist_map_break:
      }
      {
        \clist_pop:NN \l_tzCdots_opt_input_clist \l_tmpb_tl
        \clist_put_right:NV \l_tzCdots_opt_tested_clist \l_tmpb_tl
      }
    }
    \clist_concat:NNN \l_tzCdots_opt_clist
                      \l_tzCdots_opt_tested_clist
                      \l_tzCdots_opt_input_clist
    \clist_if_empty:NF \l_tzCdots_opt_clist
    {
      \tl_set:Nx \l_tzCdots_opt_tl { \clist_use:Nn \l_tzCdots_opt_clist {,} }
    }
 }

 \tzCdots_check_token:n
}

\cs_new:Npn \tzCdots_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzCdots_sub_fn #1 }
%  { \tzCdots_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzCdots_sub_fn #1 }
   { ; } { \tzCdots_late_opt_fn }
 }
 {
%    \tzCdots_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzCdots_sub_fn { r() +G{} >{\TrimSpaces}o }
{
%%%%%% to use string replacement for label positions
 \IfValueTF { #3 }
 {
       \tl_if_in:nnTF { #3 } { [ }
   { \extract_posopt:w #3 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #3 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #3 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%
 \bool_if:NTF \l_tzCdots_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzCdots_cmd_tl
   {
     ( [ shift = { (\l_tzCdots_shift_coor_tl) } ]#1 ) circle (\tzCdotradius)
   }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tzCdots_cmd_tl { (#1) circle (\tzCdotradius) }
 }

 \tl_put_right:Nx \l_tzCdots_cmd_tl
 {
   node
   [ inner~sep = 0pt ,
     label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #2 } } % pos_str
   ] {}
 }
 \tzCdots_check_token:n
}

\NewDocumentCommand\tzCdots_late_opt_fn { d() }
{
 \IfValueT { #1 }
   {
     \bool_if:NF \l_tzCdots_size_call_bool
     { \renewcommand\tzCdotradius { #1 } }
   }

 \tzCdots_stop_action
}

\NewDocumentCommand\tzCdots_stop_action {}
{
 \tl_if_empty:NTF \l_tzCdots_opt_tl
 {
   \tl_put_left:Nn \l_tzCdots_cmd_tl { ] }
 }
 {
   \tl_put_left:No \l_tzCdots_cmd_tl { \l_tzCdots_opt_tl ] }  % expand `once'
 }

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_left:Nn \l_tzCdots_cmd_tl { [ fill , solid , thin , }
 }
 {
   \tl_put_left:Nn \l_tzCdots_cmd_tl { [ solid , thin , }
 }

 \exp_last_unbraced:Nf \draw \l_tzCdots_cmd_tl ;

 \bool_set_false:N \l_tzCdots_size_call_bool
}

%%% --- end of \tzcdots


%%% \tzshoworigin  (node text and dot at the origin)

\NewDocumentCommand\tzshoworigin
 { s O{} d<> D(){0,0} +g O{} D(){\tz@initial@dot@size} }
{
 \IfValueTF { #5 }
 {% if shift
   \IfValueTF { #3 }
   {
     \path [ shift = {(#3)} ] (#4) node
       [ text~height = 1.25ex , text~depth=.25ex , below~left , #6 ]
       { #5 } ;
     \IfBooleanT { #1 } { \tzdot* [ #2 ] ([shift={(#3)}] #4) (#7) }
   }
   {% no shift
     \path (#4) node
       [ text~height = 1.25ex , text~depth=.25ex , below~left , #6 ]
       { #5 } ;
     \IfBooleanT { #1 } { \tzdot* [ #2 ] (#4) (#7) }
   }
 }
 {
   \IfValueTF { #3 }
   {% if shift
     \IfBooleanTF { #1 }
     {
       \tzdot* [ #2 ] ([shift={(#3)}] #4) (#7)
     }
     {
       \path [ shift = {(#3)} ] (#4) node
         [ text~height = 1.25ex , text~depth=.25ex , below~left , #6 ]
         { 0 } ;
     }
   }
   {% no shift
     \IfBooleanTF { #1 }
     {
       \tzdot* [ #2 ] (#4) (#7)
     }
     {
       \path (#4) node
         [ text~height = 1.25ex , text~depth=.25ex , below~left , #6 ]
         { 0 } ;
     }
   }
 }
}

%%% --- end of \tzshoworigin


%%%%% Coordinates

%%% \tzcoor()(){label}[pos]
\NewDocumentCommand\tzcoor{ s O{} d<> r() r() +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzcoor_cmd_tl

 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   {
     \path ([shift={(#3)}]#4) coordinate (#5) ;
     \tzdot*[#2]([shift={(#3)}]#4){#6}[#7](#8)
   }
   {
     \path (#4) coordinate (#5) ;
     \tzdot*[#2](#4){#6}[#7](#8)
   }
 }
 {
   \IfValueTF { #3 }
   {
     \tl_put_right:Nn \l_tzcoor_cmd_tl
       {
         ([shift={(#3)}]#4) coordinate
       }
   }
   { \tl_put_right:Nn \l_tzcoor_cmd_tl { (#4) coordinate } }

   \tl_put_right:Nn \l_tzcoor_cmd_tl
     {
       [ inner~sep = 0pt ,
     }
%%%%%% to use string replacement for label positions
 \IfValueTF { #7 }
 {
       \tl_if_in:nnTF { #7 } { [ }
   { \extract_posopt:w #7 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #7 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #7 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%
   \tl_put_right:Nx \l_tzcoor_cmd_tl
     {
         label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #6 } } % pos_str
     }
   \tl_put_right:Nn \l_tzcoor_cmd_tl
     {
       ] (#5)
     }
   \exp_last_unbraced:No \path \l_tzcoor_cmd_tl ;
 }
}

%%% --- end of \tzcoor


%%% \tzcoors

\bool_new:N \l_tzcoors_shift_coor_bool

%%% \tzcoors*[opt]<radius> ()(){}[] ()(){}[] repeated ()(){}[];
%% repeat pattern: (coor)(name){label}[pos]

%%% \tzcoors (main)
\NewDocumentCommand\tzcoors{ s O{} d<> }
{
 \tl_clear:N \l_tzcoors_cmd_tl
 \tl_clear:N \l_tzcoors_tzdot_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfValueTF { #2 }
 { \tl_set:Nn \l_tzcoors_opt_tl { #2 } }
 { \tl_clear:N \l_tzcoors_opt_tl }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzcoors_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzcoors_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzcoors_shift_coor_tl
   \bool_set_false:N \l_tzcoors_shift_coor_bool
 }

 \tzcoors_check_token:n
}

\cs_new:Npn \tzcoors_check_token:n #1
{
%  \str_if_eq:nnTF { #1 } { ( }
%    { \tzcoors_sub_fn ( }
%    { \tzcoors_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzcoors_sub_fn #1 }
   { ; } { \tzcoors_late_opt_fn }
 }
 {
%    \tzcoors_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzcoors_sub_fn { r() r() +G{} >{\TrimSpaces}o }
{
%%%%%% to use string replacement for label positions
 \IfValueTF { #4 }
 {
       \tl_if_in:nnTF { #4 } { [ }
   { \extract_posopt:w #4 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #4 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #4 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%
 \bool_if:NTF \l_tmpa_bool
 {
   % collect only coor info
   \bool_if:NTF \l_tzcoors_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzcoors_cmd_tl
     { ([ shift = { (\l_tzcoors_shift_coor_tl) } ]#1) }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzcoors_cmd_tl { (#1) }
   }
   \tl_put_right:Nn \l_tzcoors_cmd_tl
     { coordinate (#2) }
   % collect dot info: (coor) [ dot opt ] {}
   \bool_if:NTF \l_tzcoors_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzcoors_tzdot_cmd_tl
     { ([ shift = { (\l_tzcoors_shift_coor_tl) } ]#1) }
   }
   {% no shift
     \tl_put_right:Nn \l_tzcoors_tzdot_cmd_tl { (#1) }
   }
   \tl_put_right:Nn \l_tzcoors_tzdot_cmd_tl
     {
       node
       [ fill , tzdot = \tzdotsize ,
     }
   \tl_put_right:Nx \l_tzcoors_tzdot_cmd_tl
     {
         label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #3 } } , % abb
     }
   \tl_put_right:No \l_tzcoors_tzdot_cmd_tl
     {
         \l_tzcoors_opt_tl  % expand `once'
       ] {}
     }
 }
 {
   \bool_if:NTF \l_tzcoors_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzcoors_cmd_tl
       { ([ shift = { (\l_tzcoors_shift_coor_tl) } ]#1) coordinate }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzcoors_cmd_tl
       { (#1) coordinate }
   }
   \tl_put_right:Nx \l_tzcoors_cmd_tl
     { [ label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #3 } } ] } % pos_str
   \tl_put_right:Nn \l_tzcoors_cmd_tl
     { (#2) }
 }
 \tzcoors_check_token:n
}

\NewDocumentCommand\tzcoors_late_opt_fn { D(){\tz@initial@dot@size} }
{
 \renewcommand\tzdotsize{ #1 }

 \tzcoors_stop_action
}

\cs_new:Npn \tzcoors_stop_action
{
 \exp_last_unbraced:Nf \path \l_tzcoors_cmd_tl ;
 \bool_if:NT \l_tmpa_bool
 { \exp_last_unbraced:Nf \path \l_tzcoors_tzdot_cmd_tl ; }
}

%%% --- end of \tzcoors


%%% \tzcoorsquick --- with labels (quick view)

\bool_new:N \l_tzcoors_quick_shift_coor_bool

%%% \tzcoorsquick (main)
\NewDocumentCommand\tzcoorsquick { s O{} d<> }
{
 \tl_clear:N \l_tzcoors_quick_cmd_tl
 \tl_clear:N \l_tzcoors_quick_tzdot_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfValueTF { #2 }
 { \tl_set:Nn \l_tzcoors_quick_opt_tl { #2 } }
 { \tl_clear:N \l_tzcoors_quick_opt_tl }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzcoors_quick_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzcoors_quick_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzcoors_quick_shift_coor_tl
   \bool_set_false:N \l_tzcoors_quick_shift_coor_bool
 }

 \tzcoors_quick_check_token:n
}

\cs_new:Npn \tzcoors_quick_check_token:n #1
{
%  \str_if_eq:nnTF { #1 } { ( }
%    { \tzcoorsquick_sub_fn ( }
%    { \tzcoorsquick_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzcoorsquick_sub_fn #1 }
   { ; } { \tzcoorsquick_late_opt_fn }
 }
 {
%    \tzcoorsquick_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

% repetition ***
\NewDocumentCommand\tzcoorsquick_sub_fn { r() r() +g >{\TrimSpaces}o }
{
 \IfValueTF { #3 }
   { \tl_set:Nx \l_label_pos_tl { \exp_not:n { #3 } } }
   { \tl_set:Nn \l_label_pos_tl { #2 } } % automatic view

%%%%%% to use string replacement for label positions
 \IfValueTF { #4 }
 {
       \tl_if_in:nnTF { #4 } { [ }
   { \extract_posopt:w #4 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #4 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #4 }
     }
   }
   \tl_set:Nx \l_tmpb_tl { \l_label_pos_str_tl } % pos_str
 }
 {
   \tl_clear:N \l_label_pos_str_tl
   \bool_if:NTF \l_tmpa_bool
   { \tl_set:Nn \l_tmpb_tl { } } % texts with dots (tikz default: above)
   { \tl_set:Nn \l_tmpb_tl { center } } % only texts
 }
%%%%%%%%%%

%  \IfValueTF { #4 }
%  {
%    \tl_set:Nx \l_tmpb_tl { \l_label_pos_str_tl } % pos_str
%  }
%  {
%    \bool_if:NTF \l_tmpa_bool
%    { \tl_set:Nn \l_tmpb_tl { } } % texts with dots (tikz default: above)
%    { \tl_set:Nn \l_tmpb_tl { center } } % only texts
%  }

%  \tl_if_empty:nTF { #4 }
%  {
%    \bool_if:NTF \l_tmpa_bool
%    { \tl_set:Nn \l_tmpb_tl { } } % texts with dots (tikz default: above)
%    { \tl_set:Nn \l_tmpb_tl { center } } % only texts
%  }
%  {
%    \tl_set:Nx \l_tmpb_tl { \exp_not:n { #4 } }
%  }

 \bool_if:NTF \l_tmpa_bool
 { %% glancing labels with dots
   % collect only coor info
   % collect only coor info
   \bool_if:NTF \l_tzcoors_quick_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzcoors_quick_cmd_tl
     { ([ shift = { (\l_tzcoors_quick_shift_coor_tl) } ]#1) }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzcoors_quick_cmd_tl { (#1) }
   }
   \tl_put_right:Nn \l_tzcoors_quick_cmd_tl
     { coordinate (#2) }
   % collect dot info: (coor) [ dot opt ] {}
   \bool_if:NTF \l_tzcoors_quick_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzcoors_quick_tzdot_cmd_tl
     { ([ shift = { (\l_tzcoors_quick_shift_coor_tl) } ]#1) }
   }
   {% no shift
     \tl_put_right:Nn \l_tzcoors_quick_tzdot_cmd_tl { (#1) }
   }
   \tl_put_right:Nn \l_tzcoors_quick_tzdot_cmd_tl
     {
       node
       [ fill , tzdot = \tzdotsize ,
     }
   \tl_put_right:Nx \l_tzcoors_quick_tzdot_cmd_tl
     {
         label = { \l_tmpb_tl \c_colon_str { \l_label_pos_tl } } ,
     }
   \tl_put_right:No \l_tzcoors_quick_tzdot_cmd_tl
     {
         \l_tzcoors_quick_opt_tl  % expand `once'
       ] {}
     }
 }
 { %% glancing just labels (right on the coors)
   % collect coor and node info
   \bool_if:NTF \l_tzcoors_quick_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzcoors_quick_cmd_tl
       { ([ shift = { (\l_tzcoors_quick_shift_coor_tl) } ]#1) coordinate }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzcoors_quick_cmd_tl
       { (#1) coordinate }
   }
   \tl_put_right:Nx \l_tzcoors_quick_cmd_tl
     { [ label = { \l_tmpb_tl \c_colon_str { \l_label_pos_tl } } ] }
   \tl_put_right:Nn \l_tzcoors_quick_cmd_tl
     { (#2) }
 }

 \tzcoors_quick_check_token:n
}

\NewDocumentCommand\tzcoorsquick_late_opt_fn{ D(){\tz@initial@dot@size} }
{
 \renewcommand\tzdotsize{ #1 }

 \tzcoorsquick_stop_action
}

\cs_new:Npn \tzcoorsquick_stop_action
{
 \exp_last_unbraced:Nf \path \l_tzcoors_quick_cmd_tl ;
 \bool_if:NT \l_tmpa_bool
 { \exp_last_unbraced:Nf \path \l_tzcoors_quick_tzdot_cmd_tl ; }
}

%%% --- end of \tzcoorsquick



%%%%% Lines

%%% \tzline
%% do not use: inner sep=0pt

%%% \tzline

\bool_new:N \g_tzline_BEGIN_cmd_bool
\bool_new:N \g_tzline_END_cmd_bool
\bool_new:N \l_tzline_shift_coor_bool

%% \tzlineAtBegin
\NewDocumentCommand\tzlineAtBegin{ m }
{
 \bool_gset_true:N \g_tzline_BEGIN_cmd_bool
 \tl_gset:No \g_tzline_BEGIN_cmd_tl { #1 }
}

%% \tzlineAtEnd
\NewDocumentCommand\tzlineAtEnd{ m }
{
 \bool_gset_true:N \g_tzline_END_cmd_bool
 \tl_gset:No \g_tzline_END_cmd_tl { #1 }
}

%%% \tzline (main)
\NewDocumentCommand\tzline{ s t+ o d<> d"" }
{
 \tl_clear:N \l_tzline_cmd_tl

 \IfBooleanTF { #1 } % (*) or not (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzline_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzline_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzline_shift_coor_tl
   \bool_set_false:N \l_tzline_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzline_opt_tl { #3 } }
 { \tl_clear:N \l_tzline_opt_tl }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tzline_namepath_tl { name~path = #5 } }
 { \tl_clear:N \l_tzline_namepath_tl }

 \tzline_check_token:n
}

\cs_new:Npn \tzline_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzline_sub_fn ( }
%  \tzline_stop_action
}

%% structure: (coorA) -- node [pos] {text} (coorB) node [pos] {text}
\NewDocumentCommand\tzline_sub_fn{ r() +G{} O{} d<> r() +G{} O{} D<>{} }
{
 % determine connect line STYLE
 \tl_set:Nn \l_tzline_STYLE_A_tl { -- }
 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzline_STYLE_C_tl { #4 }
 }
 {
   \bool_if:NTF \l_tmpb_bool
     { \tl_set:Nn \l_tzline_STYLE_C_tl { ++ } }
     { \tl_set:Nn \l_tzline_STYLE_C_tl {    } }
 }
 % insert connect line STYLE
 \bool_if:NTF \l_tzline_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzline_cmd_tl
   { ([ shift = { (\l_tzline_shift_coor_tl) } ]#1) }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tzline_cmd_tl { (#1) }
 }

 \tl_put_right:No \l_tzline_cmd_tl  % once
   {
     \l_tzline_STYLE_A_tl %% just --
   }
 \tl_put_right:Nn \l_tzline_cmd_tl
   {
     ~ node [ above , #3 ] { #2 }
   }
 \tl_put_right:No \l_tzline_cmd_tl  % once
   {
     \l_tzline_STYLE_C_tl
   }
 \bool_if:NTF \l_tmpb_bool
 {% if ++
   \tl_put_right:Nn \l_tzline_cmd_tl { (#5) }
 }
 {% no ++
   \bool_if:NTF \l_tzline_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzline_cmd_tl
     { ([ shift = { (\l_tzline_shift_coor_tl) } ]#5) }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzline_cmd_tl { (#5) }
   }
 }

 \tl_put_right:Nn \l_tzline_cmd_tl
   { node [ #7 ] { #6 } }
 % add at begin/end
 \bool_if:NT \g_tzline_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzline_cmd_tl { \g_tzline_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzline_END_cmd_bool
   { \tl_put_right:Nx \l_tzline_cmd_tl { \g_tzline_END_cmd_tl } }

 % final action
 \tl_put_left:No \l_tzline_cmd_tl
 {
   \l_tzline_opt_tl ] % expand `once'
 }

 \tl_put_left:Nx \l_tzline_cmd_tl
     { [ \l_tzline_namepath_tl , }

 \exp_last_unbraced:Nf \draw \l_tzline_cmd_tl #8 ;

 \bool_gset_false:N \g_tzline_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzline_END_cmd_bool
%  \tl_clear:N \g_tzline_BEGIN_cmd_tl
%  \tl_clear:N \g_tzline_END_cmd_tl
}

%%% --- end of \tzline


%%% \tzlines

\bool_new:N \g_tzlines_BEGIN_cmd_bool
\bool_new:N \g_tzlines_END_cmd_bool
\bool_new:N \l_tzlines_shift_coor_bool

%% \tzlinesAtBegin
\NewDocumentCommand\tzlinesAtBegin{ m }
{
 \bool_gset_true:N \g_tzlines_BEGIN_cmd_bool
 \tl_gset:No \g_tzlines_BEGIN_cmd_tl { #1 }
}

%% \tzlinesAtEnd
\NewDocumentCommand\tzlinesAtEnd{ m }
{
 \bool_gset_true:N \g_tzlines_END_cmd_bool
 \tl_gset:No \g_tzlines_END_cmd_tl { #1 }
}

%%% \tzlines (main)
%% do not use: inner sep=0pt
\NewDocumentCommand\tzlines{ s t+ O{} d<> D""{} }
{
 \tl_clear:N \l_tzlines_cmd_tl
 \tl_clear:N \l_tzlines_STYLE_tl

 \IfBooleanTF { #1 } % (*) or not (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzlines_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzlines_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzlines_shift_coor_tl
   \bool_set_false:N \l_tzlines_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzlines_opt_tl { #3 } }
 { \tl_clear:N \l_tzlines_opt_tl }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tzlines_namepath_tl { name~path = #5 } }
 { \tl_clear:N \l_tzlines_namepath_tl }

 \int_zero:N \l_tmpa_int
 \tzlines_check_token:n
}

\cs_new:Npn \tzlines_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzlines_sub_fn #1 }
%  { \tzlines_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzlines_sub_fn #1 }
   { ; } { \tzlines_late_opt_fn }
 }
 {
%    \tzlines_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzlines_sub_fn{ r() +G{} O{} d<> }
{
 \int_incr:N \l_tmpa_int
 % (from the second round) put line STYLE before the next cmd-tl
 \int_compare:nT { \l_tmpa_int > 1 }
 {
   \tl_put_right:No \l_tzlines_cmd_tl { \l_tzlines_STYLE_tl }
   \tl_clear:N \l_tzlines_STYLE_tl
 }

 % collect cmd-tl
 \bool_if:NTF \l_tzlines_shift_coor_bool
 {% shift-coor
   \bool_if:NTF \l_tmpb_bool
   {% if ++
     \int_compare:nTF { \l_tmpa_int > 1 }
     { \tl_put_right:Nn \l_tzlines_cmd_tl { (#1) } } % no shift from 2nd
     {
       \tl_put_right:Nx \l_tzlines_cmd_tl
       { ([ shift = { (\l_tzlines_shift_coor_tl) } ]#1) } % shift first
     }
   }
   {% no ++
     \tl_put_right:Nx \l_tzlines_cmd_tl
     { ([ shift = { (\l_tzlines_shift_coor_tl) } ]#1) } % shift all coors
   }
 }
 { \tl_put_right:Nn \l_tzlines_cmd_tl { (#1) } } % no shift (normal)

 % (from the first round on) determine and save STYLE
 % determine connect line STYLE
 \tl_set:Nn \l_tzlines_STYLE_A_tl { -- }
 % save node info (for later use, at the end)
 \tl_set:Nn \l_tzlines_STYLE_B_tl { ~ node [ #3 ] { #2 } }
 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzlines_STYLE_C_tl { #4 } % empty, + , or ++
 }
 {
   \bool_if:NTF \l_tmpb_bool
     { \tl_set:Nn \l_tzlines_STYLE_C_tl { ++ } }
     { \tl_set:Nn \l_tzlines_STYLE_C_tl {    } }
 }

 \tl_put_right:No \l_tzlines_STYLE_tl { \l_tzlines_STYLE_A_tl }
 \tl_put_right:No \l_tzlines_STYLE_tl { \l_tzlines_STYLE_B_tl }
 \tl_put_right:No \l_tzlines_STYLE_tl { \l_tzlines_STYLE_C_tl }

 \tzlines_check_token:n
}

\NewDocumentCommand\tzlines_late_opt_fn { D<>{} }
{
 \tl_set:Nn \l_tzlines_code_at_end_tl { #1 }
 \tzlines_stop_action
}

\NewDocumentCommand\tzlines_stop_action {}
{
 \tl_put_right:No \l_tzlines_cmd_tl { \l_tzlines_STYLE_B_tl }
 \tl_clear:N \l_tzlines_STYLE_tl
 % add at begin/end
 \bool_if:NT \g_tzlines_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzlines_cmd_tl { \g_tzlines_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzlines_END_cmd_bool
   { \tl_put_right:Nx \l_tzlines_cmd_tl { \g_tzlines_END_cmd_tl } }
 % gathering options
 \tl_put_left:No \l_tzlines_cmd_tl
 {
   \l_tzlines_opt_tl ]    % expand `once' needed
 }
 \tl_put_left:Nx \l_tzlines_cmd_tl
   { [ \l_tzlines_namepath_tl , }
 % final action
 \exp_last_unbraced:Nf
   \draw \l_tzlines_cmd_tl \l_tzlines_code_at_end_tl ;

 \bool_gset_false:N \g_tzlines_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzlines_END_cmd_bool
%  \tl_clear:N \g_tzlines_BEGIN_cmd_tl
%  \tl_clear:N \g_tzlines_END_cmd_tl
}

%%% --- end of \tzlines


%%% \tzpolygon (closed path of \tzlines)

\bool_new:N \l_tzpolygon_shift_coor_bool

%%% \tzpolygon (main)
%% do not use: inner sep=0pt
\NewDocumentCommand\tzpolygon{ s t+ O{} d<> D""{} }
{
 \tl_clear:N \l_tzpolygon_cmd_tl
 \tl_clear:N \l_tzpolygon_STYLE_tl

 \IfBooleanTF { #1 } % fill(*) or not
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzpolygon_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzpolygon_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzpolygon_shift_coor_tl
   \bool_set_false:N \l_tzpolygon_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nx \l_tzpolygon_opt_tl { #3 } }
 { \tl_clear:N \l_tzpolygon_opt_tl }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tzpolygon_namepath_tl { name~path = #5 } }
 { \tl_clear:N \l_tzpolygon_namepath_tl }

 \int_zero:N \l_tmpa_int
 \tzpolygon_check_token:n
}

\cs_new:Npn \tzpolygon_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzpolygon_sub_fn #1 }
%  { \tzpolygon_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzpolygon_sub_fn #1 }
   { ; } { \tzpolygon_late_opt_fn }
 }
 {
%    \tzpolygon_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzpolygon_sub_fn{ r() +G{} O{} d<> }
{
 \int_incr:N \l_tmpa_int
 % (from the second round) put line STYLE before the next cmd-tl
 \int_compare:nT { \l_tmpa_int > 1 }
 {
   \tl_put_right:No \l_tzpolygon_cmd_tl { \l_tzpolygon_STYLE_tl }
   \tl_clear:N \l_tzpolygon_STYLE_tl
 }

 % collect cmd-tl
 \bool_if:NTF \l_tzpolygon_shift_coor_bool
 {% shift-coor
   \bool_if:NTF \l_tmpb_bool
   {% if ++
     \int_compare:nTF { \l_tmpa_int > 1 }
     { \tl_put_right:Nn \l_tzpolygon_cmd_tl { (#1) } } % no shift from 2nd
     {
       \tl_put_right:Nx \l_tzpolygon_cmd_tl
       { ([ shift = { (\l_tzpolygon_shift_coor_tl) } ]#1) } % shift first
     }
   }
   {% no ++
     \tl_put_right:Nx \l_tzpolygon_cmd_tl
     { ([ shift = { (\l_tzpolygon_shift_coor_tl) } ]#1) } % shift all coors
   }
 }
 { \tl_put_right:Nn \l_tzpolygon_cmd_tl { (#1) } } % no shift (normal)

 % (from the first round on) determine and save STYLE
 % determine connect line STYLE
 \tl_set:Nn \l_tzpolygon_STYLE_A_tl { -- }
 % save node info (for later use, at the end)
 \tl_set:Nn \l_tzpolygon_STYLE_B_tl { ~ node [ #3 ] { #2 } }
 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzpolygon_STYLE_C_tl { #4 } % empty, + , or ++
 }
 {
   \bool_if:NTF \l_tmpb_bool
     { \tl_set:Nn \l_tzpolygon_STYLE_C_tl { ++ } }
     { \tl_set:Nn \l_tzpolygon_STYLE_C_tl {    } }
 }

 \tl_put_right:No \l_tzpolygon_STYLE_tl { \l_tzpolygon_STYLE_A_tl }
 \tl_put_right:No \l_tzpolygon_STYLE_tl { \l_tzpolygon_STYLE_B_tl }
 \tl_put_right:No \l_tzpolygon_STYLE_tl { \l_tzpolygon_STYLE_C_tl }

 \tzpolygon_check_token:n
}

\NewDocumentCommand\tzpolygon_late_opt_fn { G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{ #1 }
 \tl_set:Nn \l_tzpolygon_code_at_end_tl { #2 }
 \tzpolygon_stop_action
}

\NewDocumentCommand\tzpolygon_stop_action {}
{
 \tl_put_right:No \l_tzpolygon_cmd_tl { \l_tzpolygon_STYLE_B_tl }
 \tl_clear:N \l_tzpolygon_STYLE_tl
 % fill or not
 \tl_put_left:No \l_tzpolygon_cmd_tl
 {
   \l_tzpolygon_opt_tl ]    % expand `once' needed
 }
 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_left:Nx \l_tzpolygon_cmd_tl
     {
       [ fill=\tzfillcolor , fill~opacity = \tzfillopacity ,
         text~opacity = 1 ,
         \l_tzpolygon_namepath_tl ,
     }
 }
 {
   \tl_put_left:Nx \l_tzpolygon_cmd_tl
     { [ \l_tzpolygon_namepath_tl , }
 }
 % final action
 \exp_last_unbraced:Nf
   \draw \l_tzpolygon_cmd_tl \l_tzpolygon_code_at_end_tl -- cycle ;
}

%%% --- end of \tzpolygon

%%(ADDED)
%%%%% Linking points

%%% \tzlink  (general version of \tzline)

\bool_new:N \g_tzlink_BEGIN_cmd_bool
\bool_new:N \g_tzlink_END_cmd_bool
\bool_new:N \l_tzlink_shift_coor_bool

%% \tzlinkAtBegin
\NewDocumentCommand\tzlinkAtBegin{ m }
{
 \bool_gset_true:N \g_tzlink_BEGIN_cmd_bool
 \tl_gset:No \g_tzlink_BEGIN_cmd_tl { #1 }
}

%% \tzlinkAtEnd
\NewDocumentCommand\tzlinkAtEnd{ m }
{
 \bool_gset_true:N \g_tzlink_END_cmd_bool
 \tl_gset:No \g_tzlink_END_cmd_tl { #1 }
}

%%% \tzlink (main)
\NewDocumentCommand\tzlink{ s t+ G{\tz@initial@link@style} o d<> d"" }
{
 \tl_clear:N \l_tzlink_cmd_tl

 \renewcommand\tzlinkstyle{ #3 }

 \IfBooleanTF { #1 } % (*) or not (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #5 }
 {
   \tl_set:Nn \l_tzlink_shift_coor_tl { #5 }
   \bool_set_true:N \l_tzlink_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzlink_shift_coor_tl
   \bool_set_false:N \l_tzlink_shift_coor_bool
 }

 \IfValueTF { #4 }
 { \tl_set:Nn \l_tzlink_opt_tl { #4 } }
 { \tl_clear:N \l_tzlink_opt_tl }


 \IfValueTF { #6 }
 { \tl_set:Nn \l_tzlink_namepath_tl { name~path = #6 } }
 { \tl_clear:N \l_tzlink_namepath_tl }

 \tzlink_check_token:n
}

\cs_new:Npn \tzlink_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzlink_sub_fn ( }
%  \tzlink_stop_action
}

\NewDocumentCommand\tzlink_sub_fn{ r() O{} +G{} O{} d<> r() +G{} O{} D<>{} }
{
 % determine connect line STYLE
 \tl_if_empty:nTF { #2 }
 {
   \tl_set:Nn \l_tzlink_STYLE_A_tl { ~ \tzlinkstyle ~ }
 }
 {
   \tl_set:Nn \l_tzlink_STYLE_A_tl { ~ #2 ~ }
 }
 \IfValueTF { #5 }
 {
   \tl_set:Nn \l_tzlink_STYLE_C_tl { #5 }     % + or ++
 }
 {
   \bool_if:NTF \l_tmpb_bool
     { \tl_set:Nn \l_tzlink_STYLE_C_tl { ++ } }
     { \tl_set:Nn \l_tzlink_STYLE_C_tl {    } }
 }
 % insert connect line STYLE
 \bool_if:NTF \l_tzlink_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzlink_cmd_tl
   { ([ shift = { (\l_tzlink_shift_coor_tl) } ]#1) }
 }
 { \tl_put_right:Nn \l_tzlink_cmd_tl { (#1) } }

 \tl_put_right:No \l_tzlink_cmd_tl          % once
   {
     \l_tzlink_STYLE_A_tl
   }
 \tl_put_right:Nn \l_tzlink_cmd_tl
   {
     ~ node [ above , #4 ] { #3 }           % above
   }
 \tl_put_right:No \l_tzlink_cmd_tl          % once
   {
     \l_tzlink_STYLE_C_tl
   }
 \bool_if:NTF \l_tmpb_bool
 {% if ++
   \tl_put_right:Nn \l_tzlink_cmd_tl { (#6) }
 }
 {% no ++
   \bool_if:NTF \l_tzlink_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzlink_cmd_tl
     { ( [ shift = { (\l_tzlink_shift_coor_tl) } ] \exp_not:n { #6 } ) }
   }
   { \tl_put_right:Nn \l_tzlink_cmd_tl { (#6) } }
 }

 \tl_put_right:Nn \l_tzlink_cmd_tl
   {
     node [ #8 ] { #7 }
   }
 % add at begin/end
 \bool_if:NT \g_tzlink_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzlink_cmd_tl { \g_tzlink_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzlink_END_cmd_bool
   { \tl_put_right:Nx \l_tzlink_cmd_tl { \g_tzlink_END_cmd_tl } }

 % final action
 \tl_put_left:No \l_tzlink_cmd_tl
 {
   \l_tzlink_opt_tl ]    % expand `once' needed
 }

 \tl_put_left:Nx \l_tzlink_cmd_tl
   { [ \l_tzlink_namepath_tl , }

 \exp_last_unbraced:Nf \draw \l_tzlink_cmd_tl #9 ;

 \bool_gset_false:N \g_tzlink_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzlink_END_cmd_bool
%  \tl_clear:N \g_tzlink_BEGIN_cmd_tl
%  \tl_clear:N \g_tzlink_END_cmd_tl
}

%%% --- end of \tzlink




%%%(ADDED)
%%% \tzlinks  -- generalized version of \tzlines

\bool_new:N \g_tzlinks_BEGIN_cmd_bool
\bool_new:N \g_tzlinks_END_cmd_bool
\bool_new:N \l_tzlinks_shift_coor_bool

%% \tzlinksAtBegin
\NewDocumentCommand\tzlinksAtBegin{ m }
{
 \bool_gset_true:N \g_tzlinks_BEGIN_cmd_bool
 \tl_gset:No \g_tzlinks_BEGIN_cmd_tl { #1 }
}

%% \tzlinksAtEnd
\NewDocumentCommand\tzlinksAtEnd{ m }
{
 \bool_gset_true:N \g_tzlinks_END_cmd_bool
 \tl_gset:No \g_tzlinks_END_cmd_tl { #1 }
}

%%% \tzlinks (main)
%% do not use: inner sep=0pt
\NewDocumentCommand\tzlinks{ s t+ G{\tz@initial@link@style} O{} d<> D""{} }
{
 \tl_clear:N \l_tzlinks_cmd_tl
 \tl_clear:N \l_tzlinks_STYLE_tl

 \IfValueT { #3 }
 { \renewcommand\tzlinkstyle{ #3 } }

 \IfBooleanTF { #1 } % (*) or not
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #5 }
 {
   \tl_set:Nn \l_tzlinks_shift_coor_tl { #5 }
   \bool_set_true:N \l_tzlinks_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzlinks_shift_coor_tl
   \bool_set_false:N \l_tzlinks_shift_coor_bool
 }

 \IfValueTF { #4 }
 { \tl_set:Nx \l_tzlinks_opt_tl { #4 } }
 { \tl_clear:N \l_tzlinks_opt_tl }

 \IfValueTF { #6 }
 { \tl_set:Nn \l_tzlinks_namepath_tl { name~path = #6 } }
 { \tl_clear:N \l_tzlinks_namepath_tl }

 \int_zero:N \l_tmpa_int
 \tzlinks_check_token:n
}

\cs_new:Npn \tzlinks_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzlinks_sub_fn #1 }
%  { \tzlinks_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzlinks_sub_fn #1 }
   { ; } { \tzlinks_late_opt_fn }
 }
 {
%    \tzlinks_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzlinks_sub_fn{ r() O{} +G{} O{} d<> }
{
 \int_incr:N \l_tmpa_int
 % (from the second round) put line STYLE before the next cmd-tl
 \int_compare:nT { \l_tmpa_int > 1 }
 {
   \tl_put_right:No \l_tzlinks_cmd_tl { \l_tzlinks_STYLE_tl }
   \tl_clear:N \l_tzlinks_STYLE_tl
 }

 % collect cmd-tl
 \bool_if:NTF \l_tzlinks_shift_coor_bool
 {% shift-coor
   \bool_if:NTF \l_tmpb_bool
   {% if ++
     \int_compare:nTF { \l_tmpa_int > 1 }
     { \tl_put_right:Nn \l_tzlinks_cmd_tl { (#1) } } % no shift from 2nd
     {
       \tl_put_right:Nx \l_tzlinks_cmd_tl
       { ([ shift = { (\l_tzlinks_shift_coor_tl) } ]#1) } % shift first
     }
   }
   {% no ++
     \tl_put_right:Nx \l_tzlinks_cmd_tl
     { ([ shift = { (\l_tzlinks_shift_coor_tl) } ]#1) } % shift all coors
   }
 }
 { \tl_put_right:Nn \l_tzlinks_cmd_tl { (#1) } } % no shift (normal)

 % (from the first round on) determine and save STYLE
 % determine connect line STYLE
 \tl_if_empty:nTF { #2 }
   { \tl_set:Nn \l_tzlinks_STYLE_A_tl { ~ \tzlinkstyle ~ } }
   { \tl_set:Nn \l_tzlinks_STYLE_A_tl { #2 } }
 % save node info (for later use, at the end)
 \tl_if_empty:nTF { #3 }
 {
   \tl_clear:N \l_tzlinks_STYLE_B_tl
 }
 {
   \tl_set:Nn \l_tzlinks_STYLE_B_tl
     { ~ node [ #4 ] { #3 } }
 }
 \IfValueTF { #5 } % <+ or ++ or none> (NOT USED!)
 {
   \tl_set:Nn \l_tzlinks_STYLE_C_tl { #5 }
 }
 {
   \bool_if:NTF \l_tmpb_bool
     { \tl_set:Nn \l_tzlinks_STYLE_C_tl { ++ } }
     { \tl_set:Nn \l_tzlinks_STYLE_C_tl {    } }
 }

 \tl_put_right:No \l_tzlinks_STYLE_tl { \l_tzlinks_STYLE_A_tl }
 \tl_put_right:No \l_tzlinks_STYLE_tl { \l_tzlinks_STYLE_B_tl }
 \tl_put_right:No \l_tzlinks_STYLE_tl { \l_tzlinks_STYLE_C_tl }

 \tzlinks_check_token:n
}

\NewDocumentCommand\tzlinks_late_opt_fn { G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{ #1 }
 \tl_set:Nn \l_tzlinks_code_at_end_tl { #2 }
 \tzlinks_stop_action
}

\NewDocumentCommand\tzlinks_stop_action {}
{
 \tl_if_empty:NF \l_tzlinks_STYLE_B_tl
 {
   \tl_put_right:No \l_tzlinks_cmd_tl { \l_tzlinks_STYLE_B_tl }
 }
 \tl_clear:N \l_tzlinks_STYLE_tl
 %% add at begin/end
 \bool_if:NT \g_tzlinks_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzlinks_cmd_tl { \g_tzlinks_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzlinks_END_cmd_bool
   { \tl_put_right:Nx \l_tzlinks_cmd_tl { \g_tzlinks_END_cmd_tl } }
 %% collect options
 \tl_put_left:No \l_tzlinks_cmd_tl
   { \l_tzlinks_opt_tl ] }          % expand `once' needed
 % * or not
 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_left:Nx \l_tzlinks_cmd_tl
     {
       [ fill=\tzfillcolor , fill~opacity = \tzfillopacity ,
         text~opacity = 1 ,
         \l_tzlinks_namepath_tl ,
     }
 }
 {
   \tl_put_left:Nx \l_tzlinks_cmd_tl
     { [ \l_tzlinks_namepath_tl , }
 }
 %% final action
%  \begin{pgfonlayer}{\tzlinklayer}  % default tzlinklayer = main
 \exp_last_unbraced:Nf
   \draw \l_tzlinks_cmd_tl \l_tzlinks_code_at_end_tl ;  %% draw (\tzlinks)
%  \end{pgfonlayer}

 \bool_gset_false:N \g_tzlinks_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzlinks_END_cmd_bool
}

%%% --- end of \tzlinks



%%% \tzpath
%%  draw=none version of \tzlinks (mainly for filling area)

\bool_new:N \g_tzfnArea_call_bool

\bool_new:N \g_tzpath_BEGIN_cmd_bool
\bool_new:N \g_tzpath_END_cmd_bool
\bool_new:N \l_tzpath_shift_coor_bool


%% \tzpathAtBegin
\NewDocumentCommand\tzpathAtBegin{ m }
{
 \bool_gset_true:N \g_tzpath_BEGIN_cmd_bool
 \tl_gset:No \g_tzpath_BEGIN_cmd_tl { #1 }
}

%% \tzpathAtEnd
\NewDocumentCommand\tzpathAtEnd{ m }
{
 \bool_gset_true:N \g_tzpath_END_cmd_bool
 \tl_gset:No \g_tzpath_END_cmd_tl { #1 }
}

%%% \tzpath (main)
%% do not use: inner sep=0pt
\NewDocumentCommand\tzpath{ s t+ G{\tz@initial@link@style} O{} d<> D""{} }
{
 \tl_clear:N \l_tzpath_cmd_tl
 \tl_clear:N \l_tzpath_STYLE_tl

 \IfValueT { #3 }
 { \renewcommand\tzpathstyle{ #3 } }

 \IfBooleanTF { #1 } % (*) or not
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #5 }
 {
   \tl_set:Nn \l_tzpath_shift_coor_tl { #5 }
   \bool_set_true:N \l_tzpath_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzpath_shift_coor_tl
   \bool_set_false:N \l_tzpath_shift_coor_bool
 }

 \IfValueTF { #4 }
 { \tl_set:Nx \l_tzpath_opt_tl { #4 } }
 { \tl_clear:N \l_tzpath_opt_tl }

 \IfValueTF { #6 }
 { \tl_set:Nn \l_tzpath_namepath_tl { name~path = #6 } }
 { \tl_clear:N \l_tzpath_namepath_tl }

 \int_zero:N \l_tmpa_int
 \tzpath_check_token:n
}

\cs_new:Npn \tzpath_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzpath_sub_fn #1 }
%  { \tzpath_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzpath_sub_fn #1 }
   { ; } { \tzpath_late_opt_fn }
 }
 {
%    \tzpath_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzpath_sub_fn{ r() O{} +G{} O{} d<> }
{
 \int_incr:N \l_tmpa_int
 % (from the second round) put line STYLE before the next cmd-tl
 \int_compare:nT { \l_tmpa_int > 1 }
 {
   \tl_put_right:No \l_tzpath_cmd_tl { \l_tzpath_STYLE_tl }
   \tl_clear:N \l_tzpath_STYLE_tl
 }

 % collect cmd-tl
 \bool_if:NTF \l_tzpath_shift_coor_bool
 {% shift-coor
   \bool_if:NTF \l_tmpb_bool
   {% if ++
     \int_compare:nTF { \l_tmpa_int > 1 }
     { \tl_put_right:Nn \l_tzpath_cmd_tl { (#1) } } % no shift from 2nd
     {
       \tl_put_right:Nx \l_tzpath_cmd_tl
       { ( [ shift = { (\l_tzpath_shift_coor_tl) } ] #1 ) } % shift first
     }
   }
   {% no ++
     \tl_put_right:Nx \l_tzpath_cmd_tl
     { ( [ shift = { (\l_tzpath_shift_coor_tl) } ] #1 ) } % shift all coors
   }
 }
 { \tl_put_right:Nn \l_tzpath_cmd_tl { (#1) } } % no shift (normal)

 % (from the first round on) determine and save STYLE
 % determine connect line STYLE
 \tl_if_empty:nTF { #2 }
   { \tl_set:Nn \l_tzpath_STYLE_A_tl { ~ \tzpathstyle ~ } }
   { \tl_set:Nn \l_tzpath_STYLE_A_tl { #2 } }
 % save node info (for later use, at the end)
 \tl_if_empty:nTF { #3 }
 {
   \tl_clear:N \l_tzpath_STYLE_B_tl
 }
 {
   \tl_set:Nn \l_tzpath_STYLE_B_tl
     { ~ node [ #4 ] { #3 } }
 }
 \IfValueTF { #5 } % <+ or ++ or none> (NOT USED!)
 {
   \tl_set:Nn \l_tzpath_STYLE_C_tl { #5 }
 }
 {
   \bool_if:NTF \l_tmpb_bool
     { \tl_set:Nn \l_tzpath_STYLE_C_tl { ++ } }
     { \tl_set:Nn \l_tzpath_STYLE_C_tl {    } }
 }

 \tl_put_right:No \l_tzpath_STYLE_tl { \l_tzpath_STYLE_A_tl }
 \tl_put_right:No \l_tzpath_STYLE_tl { \l_tzpath_STYLE_B_tl }
 \tl_put_right:No \l_tzpath_STYLE_tl { \l_tzpath_STYLE_C_tl }

 \tzpath_check_token:n
}

% \tzpath fill opacity : 0.3 (default)         % differ from \tzlinks
\NewDocumentCommand\tzpath_late_opt_fn { G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{ #1 }
 \tl_set:Nn \l_tzpath_code_at_end_tl { #2 }
 \tzpath_stop_action
}

\NewDocumentCommand\tzpath_stop_action {}
{
 \tl_if_empty:NF \l_tzpath_STYLE_B_tl
 {
   \tl_put_right:No \l_tzpath_cmd_tl { \l_tzpath_STYLE_B_tl }
 }
 \tl_clear:N \l_tzpath_STYLE_tl
 %% add at begin/end
 \bool_if:NT \g_tzpath_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzpath_cmd_tl { \g_tzpath_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzpath_END_cmd_bool
   { \tl_put_right:Nx \l_tzpath_cmd_tl { \g_tzpath_END_cmd_tl } }
 %% collect options
 \tl_put_left:No \l_tzpath_cmd_tl
   { \l_tzpath_opt_tl ] }          % expand `once' needed
 % * or not
 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_left:Nx \l_tzpath_cmd_tl
     {
       [ fill=\tzfillcolor , fill~opacity = \tzfillopacity ,
         text~opacity = 1 ,
         \l_tzpath_namepath_tl ,
     }
 }
 {
   \tl_put_left:Nx \l_tzpath_cmd_tl
     { [ \l_tzpath_namepath_tl , }
 }
 %% final action
 \bool_if:NTF \g_tzfnArea_call_bool
 { % (ADDED) for \tzfnArealayer
   \begin{pgfonlayer}{\tzfnArealayer}  % default tzpathlayer = main
   \exp_last_unbraced:Nf
     \path \l_tzpath_cmd_tl \l_tzpath_code_at_end_tl ;  %% path (\tzpath)
   \end{pgfonlayer}
 }
 { % for original \tzpath
   \begin{pgfonlayer}{\tzpathlayer}  % default tzpathlayer = main
   \exp_last_unbraced:Nf
     \path \l_tzpath_cmd_tl \l_tzpath_code_at_end_tl ;  %% path (\tzpath)
   \end{pgfonlayer}
 }
 \bool_gset_false:N \g_tzpath_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzpath_END_cmd_bool
}

%%% --- end of \tzpath


%%% \tzto

\bool_new:N \g_tzto_BEGIN_cmd_bool
\bool_new:N \g_tzto_END_cmd_bool
\bool_new:N \l_tzto_shift_coor_bool

%% \tztoAtBegin
\NewDocumentCommand\tztoAtBegin{ m }
{
 \bool_gset_true:N \g_tzto_BEGIN_cmd_bool
 \tl_gset:No \g_tzto_BEGIN_cmd_tl { #1 }
}

%% \tztoAtEnd
\NewDocumentCommand\tztoAtEnd{ m }
{
 \bool_gset_true:N \g_tzto_END_cmd_bool
 \tl_gset:No \g_tzto_END_cmd_tl { #1 }
}

%%% \tzto (main)
\NewDocumentCommand\tzto{ s t+ o d<> d"" }
{
 \tl_clear:N \l_tzto_cmd_tl

 \IfBooleanTF { #1 } % (*) or not  (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzto_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzto_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzto_shift_coor_tl
   \bool_set_false:N \l_tzto_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzto_opt_tl { #3 } }
 { \tl_clear:N \l_tzto_opt_tl }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tzto_namepath_tl { name~path = #5 } }
 { \tl_clear:N \l_tzto_namepath_tl }

 \tzto_check_token:n
}

\cs_new:Npn \tzto_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzto_sub_fn ( }
%  \tzto_stop_action
}

\NewDocumentCommand\tzto_sub_fn{ r() +G{} O{} r() +G{} O{} D<>{} }
{

 \bool_if:NTF \l_tzto_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzto_cmd_tl
   { ([ shift = { (\l_tzto_shift_coor_tl) } ]#1) }
 }
 { \tl_put_right:Nn \l_tzto_cmd_tl { (#1) } }

 \tl_put_right:Nn \l_tzto_cmd_tl
   { to ~node [ above , #3 ] { #2 } }

 \bool_if:NTF \l_tmpb_bool
 {% if ++
   \tl_put_right:Nn \l_tzto_cmd_tl { ++ (#4) }
 }
 {% no ++
   \bool_if:NTF \l_tzto_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzto_cmd_tl
     { ([ shift = { (\l_tzto_shift_coor_tl) } ]#4) }
   }
   { \tl_put_right:Nn \l_tzto_cmd_tl { (#4) } }
 }

 \tl_put_right:Nn \l_tzto_cmd_tl
   { node [ #6 ] { #5 } }

 % add at begin/end
 \bool_if:NT \g_tzto_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzto_cmd_tl { \g_tzto_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzto_END_cmd_bool
   { \tl_put_right:Nx \l_tzto_cmd_tl { \g_tzto_END_cmd_tl } }

 % final action
 \tl_put_left:No \l_tzto_cmd_tl
 {
   \l_tzto_opt_tl ]    % expand `once' needed
 }

 \tl_put_left:Nx \l_tzto_cmd_tl
   { [ \l_tzto_namepath_tl , }

 \exp_last_unbraced:Nf \draw \l_tzto_cmd_tl #7 ;

 \bool_gset_false:N \g_tzto_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzto_END_cmd_bool
%  \tl_clear:N \g_tzto_BEGIN_cmd_tl
%  \tl_clear:N \g_tzto_END_cmd_tl
}

%%% --- end of \tzto


%%% \tztos (longer version of \tzto)

\bool_new:N \g_tztos_BEGIN_cmd_bool
\bool_new:N \g_tztos_END_cmd_bool
\bool_new:N \l_tztos_shift_coor_bool

%% \tztosAtBegin
\NewDocumentCommand\tztosAtBegin{ m }
{
 \bool_gset_true:N \g_tztos_BEGIN_cmd_bool
 \tl_gset:No \g_tztos_BEGIN_cmd_tl { #1 }
}

%% \tztosAtEnd
\NewDocumentCommand\tztosAtEnd{ m }
{
 \bool_gset_true:N \g_tztos_END_cmd_bool
 \tl_gset:No \g_tztos_END_cmd_tl { #1 }
}

%%% \tztos (main)
%% do not use: inner sep=0pt
\NewDocumentCommand\tztos{ s t+ O{} d<> D""{} }
{
 \tl_clear:N \l_tztos_cmd_tl
 \tl_clear:N \l_tztos_STYLE_tl

%  \IfValueT { #3 }
%  { \renewcommand\tztostyle{ #3 } }

 \IfBooleanTF { #1 } % (*) or not  (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tztos_shift_coor_tl { #4 }
   \bool_set_true:N \l_tztos_shift_coor_bool
 }
 {
   \tl_clear:N \l_tztos_shift_coor_tl
   \bool_set_false:N \l_tztos_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tztos_opt_tl { #3 } }
 { \tl_clear:N \l_tztos_opt_tl }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tztos_namepath_tl { name~path = #5 } }
 { \tl_clear:N \l_tztos_namepath_tl }

 \int_zero:N \l_tmpa_int
 \tztos_check_token:n
}

\cs_new:Npn \tztos_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tztos_sub_fn #1 }
%  { \tztos_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tztos_sub_fn #1 }
   { ; } { \tztos_late_opt_fn }
 }
 {
%    \tztos_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

%% (coor)[to opt]{text}[node opt]
\NewDocumentCommand\tztos_sub_fn{ r() O{} +G{} O{} }
{
 \int_incr:N \l_tmpa_int
 % (from the second round) put line STYLE before the next cmd-tl
 \int_compare:nT { \l_tmpa_int > 1 }
 {
   \tl_put_right:No \l_tztos_cmd_tl { \l_tztos_STYLE_tl }
   \tl_clear:N \l_tztos_STYLE_tl
 }

 % collect cmd-tl
 \bool_if:NTF \l_tztos_shift_coor_bool
 {% shift-coor
   \bool_if:NTF \l_tmpb_bool
   {% if ++
     \int_compare:nTF { \l_tmpa_int > 1 }
     { \tl_put_right:Nn \l_tztos_cmd_tl { (#1) } } % no shift from 2nd
     {
       \tl_put_right:Nx \l_tztos_cmd_tl
       { ([ shift = { (\l_tztos_shift_coor_tl) } ]#1) } % shift first
     }
   }
   {% no ++
     \tl_put_right:Nx \l_tztos_cmd_tl
     { ([ shift = { (\l_tztos_shift_coor_tl) } ]#1) } % shift all coors
   }
 }
 { \tl_put_right:Nn \l_tztos_cmd_tl { (#1) } } % no shift (normal)

 % (from the first round on) determine and save STYLE
 % determine connect line STYLE
 \tl_set:Nn \l_tztos_STYLE_A_tl { ~ to [ #2 ] }
 % save node info (for later use, at the end)
 \tl_if_empty:nTF { #3 }
 {
   \tl_clear:N \l_tztos_STYLE_B_tl
 }
 {
   \tl_set:Nn \l_tztos_STYLE_B_tl
     { ~ node [ #4 ] { #3 } }
 }
 \bool_if:NTF \l_tmpb_bool
   { \tl_set:Nn \l_tztos_STYLE_C_tl { ++ } }
   { \tl_set:Nn \l_tztos_STYLE_C_tl {    } }

 \tl_put_right:No \l_tztos_STYLE_tl { \l_tztos_STYLE_A_tl }
 \tl_put_right:No \l_tztos_STYLE_tl { \l_tztos_STYLE_B_tl }
 \tl_put_right:No \l_tztos_STYLE_tl { \l_tztos_STYLE_C_tl }

 \tztos_check_token:n
}

\NewDocumentCommand\tztos_late_opt_fn { D<>{} }
{
 \tl_set:Nn \l_tztos_code_at_end_tl { #1 }
 \tztos_stop_action
}

\NewDocumentCommand\tztos_stop_action {}
{
 \tl_if_empty:NF \l_tztos_STYLE_B_tl
 {
   \tl_put_right:No \l_tztos_cmd_tl { \l_tztos_STYLE_B_tl }
 }
 \tl_clear:N \l_tztos_STYLE_tl
 % add at begin/end
 \bool_if:NT \g_tztos_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tztos_cmd_tl { \g_tztos_BEGIN_cmd_tl } }
 \bool_if:NT \g_tztos_END_cmd_bool
   { \tl_put_right:Nx \l_tztos_cmd_tl { \g_tztos_END_cmd_tl } }
 % fill or not
 \tl_put_left:No \l_tztos_cmd_tl
 {
   \l_tztos_opt_tl ]    % expand `once' needed for user convenience
 }
 \tl_put_left:Nx \l_tztos_cmd_tl
   { [ \l_tztos_namepath_tl , }
 % final action
 \exp_last_unbraced:Nf
   \draw \l_tztos_cmd_tl \l_tztos_code_at_end_tl ;  %% draw

 \bool_gset_false:N \g_tztos_BEGIN_cmd_bool
 \bool_gset_false:N \g_tztos_END_cmd_bool
%  \tl_clear:N \g_tztos_BEGIN_cmd_tl
%  \tl_clear:N \g_tztos_END_cmd_tl
}

%%% --- end of \tztos


%%(ADDED)
%%% \tzedge

\bool_new:N \l_tzedge_shift_coor_bool

%%% \tzedge (main)
\NewDocumentCommand\tzedge{ s t+ o d<> }
{
 \tl_clear:N \l_tzedge_cmd_tl

 \IfBooleanTF { #1 } % (*) or not  (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzedge_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzedge_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzedge_shift_coor_tl
   \bool_set_false:N \l_tzedge_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzedge_opt_tl { #3 } }
 { \tl_clear:N \l_tzedge_opt_tl }

 \tzedge_check_token:n
}

\cs_new:Npn \tzedge_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzedge_sub_fn ( }
%  \tzedge_stop_action
}

\NewDocumentCommand\tzedge_sub_fn{ r() +G{} O{} r() +G{} O{} D<>{} }
{
 \bool_if:NTF \l_tzedge_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzedge_cmd_tl
   { ([ shift = { (\l_tzedge_shift_coor_tl) } ]#1) }
 }
 { \tl_put_right:Nn \l_tzedge_cmd_tl { (#1) } }

 \tl_put_right:Nn \l_tzedge_cmd_tl
   { edge [ }
 \tl_put_right:No \l_tzedge_cmd_tl
   { \l_tzedge_opt_tl ] } % expand `once' needed
 \tl_put_right:Nn \l_tzedge_cmd_tl
   { node [ #3 ] { #2 } }


 \bool_if:NTF \l_tmpb_bool
 {% if ++
   \tl_put_right:Nn \l_tzedge_cmd_tl { ++ (#4) ++ (#4) }
 }
 {% no ++
   \bool_if:NTF \l_tzedge_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzedge_cmd_tl
     {
       ([ shift = { (\l_tzedge_shift_coor_tl) } ]#4)
       ([ shift = { (\l_tzedge_shift_coor_tl) } ]#4)
     }
   }
   { \tl_put_right:Nn \l_tzedge_cmd_tl { (#4) (#4) } }
 }

 \tl_if_empty:nF { #5 }
 {
   \tl_put_right:Nn \l_tzedge_cmd_tl
   { node [ #6 ] { #5 } }
 }

 % final action
 \exp_last_unbraced:Nf \draw \l_tzedge_cmd_tl #7 ;
}

%%% --- end of \tzedge


%%(ADDED)
%%% \tzedges  -- generalized version of \tzlines

\bool_new:N \l_tzedges_shift_coor_bool

%%% \tzedges (main)
%% do not use: inner sep=0pt
\NewDocumentCommand\tzedges{ s t+ O{} d<> }
{
 \tl_clear:N \l_tzedges_cmd_tl
 \tl_clear:N \l_tzedges_STYLE_tl

%  \IfValueT { #3 }
%  { \renewcommand\tzedgestyle{ #3 } }

 \IfBooleanTF { #1 } % (*) or not  (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzedges_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzedges_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzedges_shift_coor_tl
   \bool_set_false:N \l_tzedges_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzedges_opt_tl { #3 } }
 { \tl_clear:N \l_tzedges_opt_tl }

 \int_zero:N \l_tmpa_int
 \tzedges_check_token:n
}

\cs_new:Npn \tzedges_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzedges_sub_fn #1 }
%  { \tzedges_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzedges_sub_fn #1 }
%    { ; } { \tzedges_late_opt_fn }
   { ; } { \tzedges_stop_action }
 }
 {
%    \tzedges_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzedges_sub_fn{ r() O{} +G{} O{} }
{
 \int_incr:N \l_tmpa_int
 % (from the second round) put line STYLE before the next cmd-tl
 \int_compare:nT { \l_tmpa_int > 1 }
 {
   \tl_put_right:No \l_tzedges_cmd_tl { \l_tzedges_STYLE_tl }
   \tl_clear:N \l_tzedges_STYLE_tl
 }

 % collect cmd-tl
 \bool_if:NTF \l_tzedges_shift_coor_bool
 {% shift-coor
   \bool_if:NTF \l_tmpb_bool
   {% if ++
     \int_compare:nTF { \l_tmpa_int > 1 }
     { \tl_put_right:Nn \l_tzedges_cmd_tl { (#1) } } % no shift from 2nd
     {
       \tl_put_right:Nx \l_tzedges_cmd_tl
       { ([ shift = { (\l_tzedges_shift_coor_tl) } ]#1) } % shift first
     }
   }
   {% no ++
     \tl_put_right:Nx \l_tzedges_cmd_tl
     { ([ shift = { (\l_tzedges_shift_coor_tl) } ]#1) } % shift all coors
   }
 }
 { \tl_put_right:Nn \l_tzedges_cmd_tl { (#1) } } % no shift (normal)

 % (from the first round on) determine and save STYLE
 % determine connect line STYLE
 \tl_set:Nn \l_tzedges_STYLE_A_tl { edge [ #2 ] }
 % save node info (for later use, at the end)
 \tl_if_empty:nTF { #3 }
 {
   \tl_clear:N \l_tzedges_STYLE_B_tl
 }
 {
   \tl_set:Nn \l_tzedges_STYLE_B_tl
     { ~ node [ #4 ] { #3 } }
 }
 \bool_if:NTF \l_tmpb_bool
   { \tl_set:Nn \l_tzedges_STYLE_C_tl { ++ } }
   { \tl_set:Nn \l_tzedges_STYLE_C_tl {    } }

 \tl_put_right:No \l_tzedges_STYLE_tl { \l_tzedges_STYLE_A_tl }
 \tl_put_right:No \l_tzedges_STYLE_tl { \l_tzedges_STYLE_B_tl }
 \tl_put_right:No \l_tzedges_STYLE_tl { \l_tzedges_STYLE_C_tl }

 \tzedges_check_token:n
}

%\NewDocumentCommand\tzedges_late_opt_fn { D<>{} }
%{
%  \tl_set:Nn \l_tzedges_code_at_end_tl { #1 }
%  \tzedges_stop_action
%}

\NewDocumentCommand\tzedges_stop_action { D<>{} }
{
 % #1 works with the first coordinate
 % because [edge] and [node] does not change the current point
 \tl_if_empty:NF \l_tzedges_STYLE_B_tl
 {
   \tl_put_right:No \l_tzedges_cmd_tl { \l_tzedges_STYLE_B_tl }
 }
 \tl_clear:N \l_tzedges_STYLE_tl

 \tl_put_left:No \l_tzedges_cmd_tl
   { [ \l_tzedges_opt_tl ] }   % expand `once' needed

 % final action
 \exp_last_unbraced:Nf
   \draw \l_tzedges_cmd_tl #1 ;  %% draw
}

%%% --- end of \tzedges


%%%%% Figures: circles, frames, ellipses, triangles, etc.

%%% \tzcircle

\NewDocumentCommand\tzcircle
 { s O{} d<> D""{} r() r() G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#7} % effective only in * version
 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   {% if shift
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             name~path = #4 , #2 ] ([shift={(#3)}]#5) circle (#6)
             #8 ;
   }
   {% no shift (normal)
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             name~path = #4 , #2 ] (#5) circle (#6)
             #8 ;
   }
 }
 {
   \IfValueTF { #3 }
   { \draw [ name~path = #4 , #2 ] ([shift={(#3)}]#5) circle (#6) #8 ; }
   { \draw [ name~path = #4 , #2 ] (#5) circle (#6) #8 ; }
 }
}

%%% \tzring

\NewDocumentCommand\tzring
 { s O{} d<> r() r() d() d() G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#8} % effective only in * version
 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   {% if shift
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             even~odd~rule , #2 ]
           ([shift={(#3)}]#4) circle (#5)
           \IfValueT { #6 } { ([shift={(#3)}]#6) circle (#7) }
           #9 ;
   }
   {% no shift (normal)
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             even~odd~rule , #2 ]
           (#4) circle (#5)
           \IfValueT { #6 } { (#6) circle (#7) }
           #9 ;
   }
 }
 {
   \IfValueTF { #3 }
   {
     \draw [ even~odd~rule , #2 ]
           ([shift={(#3)}]#4) circle (#5)
           \IfValueT { #6 } { ([shift={(#3)}]#6) circle (#7) }
           #9 ;
   }
   {
     \draw [ even~odd~rule , #2 ]
           (#4) circle (#5)
           \IfValueT { #6 } { (#6) circle (#7) }
           #9 ;
   }
 }
}

%%% --- end of \tzring

\let\tzcirclering\tzring


%%% \tzellipse

\NewDocumentCommand\tzellipse
 { s O{} d<> D""{} r() r() G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#7} % effective only in * version
 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   {% if shift
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             name~path = #4 , #2 ]
           ([shift={(#3)}]#5) ellipse (#6)
           #8 ;
   }
   {% no shift (normal)
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             name~path = #4 , #2 ]
           (#5) ellipse (#6)
           #8 ;
   }
 }
 {
   \IfValueTF { #3 }
   { \draw [ name~path = #4 , #2 ] ([shift={(#3)}]#5) ellipse (#6) #8 ; }
   { \draw [ name~path = #4 , #2 ] (#5) ellipse (#6) #8 ; }
 }
}

%%% --- end of \tzellipse

\let\tzoval\tzellipse


%%% \tzellipsering

\NewDocumentCommand\tzellipsering
 { s O{} d<> r() r() d() d() G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#8} % effective only in * version
 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   {% if shift
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             even~odd~rule , #2 ]
           ([shift={(#3)}]#4) ellipse (#5)
           \IfValueT { #6 } { ([shift={(#3)}]#6) ellipse (#7) }
           #9 ;
   }
   {% no shift (normal)
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             even~odd~rule , #2 ]
           (#4) ellipse (#5)
           \IfValueT { #6 } { (#6) ellipse (#7) }
           #9 ;
   }
 }
 {
   \IfValueTF { #3 }
   {
     \draw [ even~odd~rule , #2 ]
           ([shift={(#3)}]#4) ellipse (#5)
           \IfValueT { #6 } { ([shift={(#3)}]#6) ellipse (#7) }
           #9 ;
   }
   {
     \draw [ even~odd~rule , #2 ]
           (#4) ellipse (#5)
           \IfValueT { #6 } { (#6) ellipse (#7) }
           #9 ;
   }
 }
}

%%% --- end of \tzellipsering

\let\tzovalring\tzellipsering


%%% \tzframe

\NewDocumentCommand\tzframe
 { s t+ O{} d<> D""{} r() r() G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#8} % effective only in * version
 \IfBooleanTF { #1 }
 {
   \IfBooleanTF { #2 }
   {
     \IfValueTF { #4 }
     {% if shift
       \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
               text~opacity = 1 ,
               name~path = #5 , #3 ]
             ([shift={(#4)}]#6) rectangle ++ (#7)
             #9 ;
     }
     {% no shift
       \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
               text~opacity = 1 ,
               name~path = #5 , #3 ]
             (#6) rectangle ++ (#7)
             #9 ;
     }
   }
   {
     \IfValueTF { #4 }
     {% if shift
       \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
               text~opacity = 1 ,
               name~path = #5 , #3 ]
             ([shift={(#4)}]#6) rectangle    ([shift={(#4)}]#7)
             #9 ;
     }
     {% no shift
       \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
               text~opacity = 1 ,
               name~path = #5 , #3 ]
             (#6) rectangle    (#7)
             #9 ;
     }
   }
 }
 {
   \IfBooleanTF { #2 }
   {
     \IfValueTF { #4 }
     {% if shift
       \draw [ name~path = #5 , #3 ]
             ([shift={(#4)}]#6) rectangle ++ (#7)
             #9 ;
     }
     {% no shift
       \draw [ name~path = #5 , #3 ] (#6) rectangle ++ (#7) #9 ;
     }
   }
   {
     \IfValueTF { #4 }
     {% if shift
       \draw [ name~path = #5 , #3 ]
             ([shift={(#4)}]#6) rectangle    ([shift={(#4)}]#7)
             #9 ;
     }
     {% no shift
       \draw [ name~path = #5 , #3 ] (#6) rectangle    (#7) #9 ;
     }
   }
 }
}
%%% --- end of \tzframe

\let\tzrectangle\tzframe
\let\tzbox\tzframe



%%% \tzrectanglering

\NewDocumentCommand\tzrectanglering
 { s O{} d<> r() r() d() d() G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#8} % effective only in * version
 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   {% if shift
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             even~odd~rule , #2 ]
           ([shift={(#3)}]#4) rectangle ([shift={(#3)}]#5)
           \IfValueT { #6 } { ([shift={(#3)}]#6) rectangle ([shift={(#3)}]#7) }
           #9 ;
   }
   {% no shift (normal)
     \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
             text~opacity = 1 ,
             even~odd~rule , #2 ]
           (#4) rectangle (#5)
           \IfValueT { #6 } { (#6) rectangle (#7) }
           #9 ;
   }
 }
 {
   \IfValueTF { #3 }
   {
     \draw [ even~odd~rule , #2 ]
           ([shift={(#3)}]#4) rectangle ([shift={(#3)}]#5)
           \IfValueT { #6 } { ([shift={(#3)}]#6) rectangle ([shift={(#3)}]#7) }
           #9 ;
   }
   {
     \draw [ even~odd~rule , #2 ]
           (#4) rectangle (#5)
           \IfValueT { #6 } { (#6) rectangle (#7) }
           #9 ;
   }
 }
}

%%% --- end of \tzrectanglering

\let\tzframering\tzrectanglering
\let\tzboxring\tzrectanglering



%%%%%%%(ADDED) -- to be removed
%%%%%%%% \tzdiamond
%%%%%
%%%%%\NewDocumentCommand\tzdiamond
%%%%%  { s O{} d<> D""{} r() r() G{\tz@initial@fill@opacity} }
%%%%%{
%%%%%  \renewcommand\tzfillopacity{#7}
%%%%%  \IfBooleanTF { #1 }
%%%%%  {
%%%%%    \IfValueTF { #3 }
%%%%%    {% if shift
%%%%%      \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
%%%%%              text~opacity = 1 , #2 ]
%%%%%            ([shift={(#3)}]$ (#5) + (#6|-0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) + (#6-|0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) - (#6|-0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) - (#6-|0,0) $) -- cycle;
%%%%%    }
%%%%%    {% no shift (normal)
%%%%%      \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
%%%%%              text~opacity = 1 , #2 ]
%%%%%            ($ (#5) + (#6|-0,0) $)
%%%%%         -- ($ (#5) + (#6-|0,0) $)
%%%%%         -- ($ (#5) - (#6|-0,0) $)
%%%%%         -- ($ (#5) - (#6-|0,0) $) -- cycle;
%%%%%    }
%%%%%  }
%%%%%  {
%%%%%    \IfValueTF { #3 }
%%%%%    {% if shift
%%%%%      \draw [ #2 ]
%%%%%            ([shift={(#3)}]$ (#5) + (#6|-0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) + (#6-|0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) - (#6|-0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) - (#6-|0,0) $) -- cycle;
%%%%%    }
%%%%%    {% no shift (normal)
%%%%%      \draw [ #2 ]
%%%%%            ($ (#5) + (#6|-0,0) $)
%%%%%         -- ($ (#5) + (#6-|0,0) $)
%%%%%         -- ($ (#5) - (#6|-0,0) $)
%%%%%         -- ($ (#5) - (#6-|0,0) $) -- cycle;
%%%%%    }
%%%%%  }
%%%%%}
%%%%%
%%%%%
%%%%%%%(ADDED) -- to be removed
%%%%%%%% \tztriangle
%%%%%
%%%%%\NewDocumentCommand\tztriangle
%%%%%  { s O{} d<> D""{} r() r() G{\tz@initial@fill@opacity} }
%%%%%{
%%%%%  \renewcommand\tzfillopacity{#7}
%%%%%  \IfBooleanTF { #1 }
%%%%%  {
%%%%%    \IfValueTF { #3 }
%%%%%    {% if shift
%%%%%      \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
%%%%%              text~opacity = 1 , name~path = #4 , #2 ]
%%%%%            ([shift={(#3)}]$ (#5) + .5*(#6|-0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) + (0,0|-#6) $)
%%%%%         -- ([shift={(#3)}]$ (#5) - .5*(#6|-0,0) $) -- cycle;
%%%%%    }
%%%%%    {% no shift
%%%%%      \draw [ fill = \tzfillcolor , fill~opacity = \tzfillopacity ,
%%%%%              text~opacity = 1 , name~path = #4 , #2 ]
%%%%%            ($ (#5) + .5*(#6|-0,0) $)
%%%%%         -- ($ (#5) + (0,0|-#6) $)
%%%%%         -- ($ (#5) - .5*(#6|-0,0) $) -- cycle;
%%%%%    }
%%%%%  }
%%%%%  {
%%%%%    \IfValueTF { #3 }
%%%%%    {% if shift
%%%%%      \draw [ name~path = #4 , #2 ]
%%%%%            ([shift={(#3)}]$ (#5) + .5*(#6|-0,0) $)
%%%%%         -- ([shift={(#3)}]$ (#5) + (0,0|-#6) $)
%%%%%         -- ([shift={(#3)}]$ (#5) - .5*(#6|-0,0) $) -- cycle;
%%%%%    }
%%%%%    {% no shift
%%%%%      \draw [ name~path = #4 , #2 ]
%%%%%            ($ (#5) + .5*(#6|-0,0) $)
%%%%%         -- ($ (#5) + (0,0|-#6) $)
%%%%%         -- ($ (#5) - .5*(#6|-0,0) $) -- cycle;
%%%%%    }
%%%%%  }
%%%%%}


%%% \tzparabola

\bool_new:N \g_tzparabola_BEGIN_cmd_bool
\bool_new:N \g_tzparabola_END_cmd_bool
\bool_new:N \l_tzparabola_shift_coor_bool

%% \tzparabolaAtBegin
\NewDocumentCommand\tzparabolaAtBegin{ m }
{
 \bool_gset_true:N \g_tzparabola_BEGIN_cmd_bool
 \tl_gset:No \g_tzparabola_BEGIN_cmd_tl { #1 }
}

%% \tzparabolaAtEnd
\NewDocumentCommand\tzparabolaAtEnd{ m }
{
 \bool_gset_true:N \g_tzparabola_END_cmd_bool
 \tl_gset:No \g_tzparabola_END_cmd_tl { #1 }
}

%% \tzparabola (main)
\NewDocumentCommand\tzparabola
{ s t+ O{} d<> D""{} }
{
 \tl_clear:N \l_tzparabola_cmd_tl

 \IfBooleanTF { #1 } % NOT USED!!!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 }
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tzparabola_pathname_tl { name~path = #5 } }
 { \tl_clear:N \l_tzparabola_pathname_tl }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzparabola_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzparabola_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzparabola_shift_coor_tl
   \bool_set_false:N \l_tzparabola_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzparabola_opt_tl { #3 } }
 { \tl_clear:N \l_tzparabola_opt_tl }

 \tzparabola_check_token:n
}

\cs_new:Npn \tzparabola_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzparabola_sub_fn ( }
%  \tzparabola_stop_action
}

\NewDocumentCommand\tzparabola_sub_fn
 { r() r() d() +G{} O{} G{\tz@initial@fill@opacity} D<>{} }
{
 \renewcommand\tzfillopacity{#6} %% NOT USED! (to be removed)

 \bool_if:NTF \l_tzparabola_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzparabola_cmd_tl
   { ([shift = { (\l_tzparabola_shift_coor_tl) } ]#1) }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tzparabola_cmd_tl { (#1) }
 }

 \IfNoValueTF { #3 }
 {%% 2 coors
   \bool_if:NTF \l_tmpb_bool
   {% if + (relative coor)
     \bool_if:NTF \l_tzparabola_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzparabola_cmd_tl
       { parabola ([shift = { (\l_tzparabola_shift_coor_tl) } ]$(#1)+(#2)$) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzparabola_cmd_tl { parabola ($(#1)+(#2)$) }
     }
   }
   {% no + (absolute coor)
     \bool_if:NTF \l_tzparabola_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzparabola_cmd_tl
       { parabola ([shift = { (\l_tzparabola_shift_coor_tl) } ]#2) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzparabola_cmd_tl { parabola (#2) }
     }
   }
 }
 {%% 3 coors
   \bool_if:NTF \l_tmpb_bool
   {% if + (relative coor)
     \tl_put_right:Nn \l_tzparabola_cmd_tl
     { parabola~bend + (#2) }
     \bool_if:NTF \l_tzparabola_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzparabola_cmd_tl
       { ([shift = { (\l_tzparabola_shift_coor_tl) } ]$(#1)+(#3)$) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzparabola_cmd_tl { ($(#1)+(#3)$) }
     }
   }
   {% no + (absolute coor)
     \bool_if:NTF \l_tzparabola_shift_coor_bool
     {
       \tl_put_right:Nx \l_tzparabola_cmd_tl
       {
         parabola~bend
         ([shift = { (\l_tzparabola_shift_coor_tl) } ]#2)
       }
     }
     {
       \tl_put_right:Nn \l_tzparabola_cmd_tl
       { parabola~bend (#2) }
     }
     \bool_if:NTF \l_tzparabola_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzparabola_cmd_tl
       { ([shift = { (\l_tzparabola_shift_coor_tl) } ]#3) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzparabola_cmd_tl { (#3) }
     }
   }
 }

 \tl_put_right:Nn \l_tzparabola_cmd_tl
   { node [ #5 ] { #4 } }
 % add at begin/end
 \bool_if:NT \g_tzparabola_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzparabola_cmd_tl { \g_tzparabola_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzparabola_END_cmd_bool
   { \tl_put_right:Nx \l_tzparabola_cmd_tl { \g_tzparabola_END_cmd_tl } }

 % final action
 \tl_put_left:No \l_tzparabola_cmd_tl
   { \l_tzparabola_opt_tl ] } % expand `once'
 \tl_put_left:Nx \l_tzparabola_cmd_tl
   { [ \l_tzparabola_pathname_tl , }

 \exp_last_unbraced:Nf
   \draw \l_tzparabola_cmd_tl #7 ;

 \bool_gset_false:N \g_tzparabola_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzparabola_END_cmd_bool
%  \tl_clear:N \g_tzparabola_BEGIN_cmd_tl
%  \tl_clear:N \g_tzparabola_END_cmd_tl
}

%%% -- end of \tzparabola


%%% \tzbezier

\bool_new:N \g_tzbezier_BEGIN_cmd_bool
\bool_new:N \g_tzbezier_END_cmd_bool
\bool_new:N \l_tzbezier_shift_coor_bool

%% \tzbezierAtBegin
\NewDocumentCommand\tzbezierAtBegin{ m }
{
 \bool_gset_true:N \g_tzbezier_BEGIN_cmd_bool
 \tl_gset:No \g_tzbezier_BEGIN_cmd_tl { #1 }
}

%% \tzbezierAtEnd
\NewDocumentCommand\tzbezierAtEnd{ m }
{
 \bool_gset_true:N \g_tzbezier_END_cmd_bool
 \tl_gset:No \g_tzbezier_END_cmd_tl { #1 }
}

%% \tzbezier (main)
\NewDocumentCommand\tzbezier{ s t+ O{} d<> D""{tzplot~path} }
{
 \tl_clear:N \l_tzbezier_cmd_tl

 \IfBooleanTF { #1 } %% NOT USED!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_true:N \l_tmpa_bool }

 \IfBooleanTF { #2 }
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #5 }
 { \tl_set:Nn \l_tzbezier_pathname_tl { name~path = #5 } }
 { \tl_clear:N \l_tzbezier_pathname_tl }

 \IfValueTF { #4 }
 {
   \tl_set:Nn \l_tzbezier_shift_coor_tl { #4 }
   \bool_set_true:N \l_tzbezier_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzbezier_shift_coor_tl
   \bool_set_false:N \l_tzbezier_shift_coor_bool
 }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzbezier_opt_tl { #3 } }
 { \tl_clear:N \l_tzbezier_opt_tl }

 \tzbezier_check_token:n
}

\cs_new:Npn \tzbezier_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzbezier_sub_fn ( }
%  \tzbezier_stop_action
}

\NewDocumentCommand\tzbezier_sub_fn{ r() r() r() d() +G{} O{} D<>{} }
{
 \bool_if:NTF \l_tzbezier_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzbezier_cmd_tl
   { ([shift = { (\l_tzbezier_shift_coor_tl) } ]#1) .. controls }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tzbezier_cmd_tl { (#1) .. controls }
 }

 \IfNoValueTF { #4 }
 {%% 3 coors
   \bool_if:NTF \l_tmpb_bool
   {% if + (relative coor)
     \tl_put_right:Nn \l_tzbezier_cmd_tl { + (#2) }
     \bool_if:NTF \l_tzbezier_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzbezier_cmd_tl
       { .. ([shift = { (\l_tzbezier_shift_coor_tl) } ]$(#1)+(#3)$) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzbezier_cmd_tl { .. ($(#1)+(#3)$) }
     }
   }
   {% no + (absolute coor)
     % control coor
     \bool_if:NTF \l_tzbezier_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzbezier_cmd_tl
       { ([ shift = { (\l_tzbezier_shift_coor_tl) } ]#2) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzbezier_cmd_tl { (#2) }
     }
     %% end coor
     \bool_if:NTF \l_tzbezier_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzbezier_cmd_tl
       { .. ([shift = { (\l_tzbezier_shift_coor_tl) } ]#3) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzbezier_cmd_tl { .. (#3) }
     }
   }
 }
 {%% 4 coors
   \bool_if:NTF \l_tmpb_bool
   {% if + (relative coor)
     \tl_put_right:Nn \l_tzbezier_cmd_tl { + (#2) and + (#3) }
     \bool_if:NTF \l_tzbezier_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzbezier_cmd_tl
       { .. ([shift = { (\l_tzbezier_shift_coor_tl) } ]$(#1)+(#4)$) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzbezier_cmd_tl { .. ($(#1)+(#4)$) }
     }
   }
   {% no + (absolute coor)
     %% control coors
     \bool_if:NTF \l_tzbezier_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzbezier_cmd_tl
       {
         ([ shift = { (\l_tzbezier_shift_coor_tl) } ]#2)
         and
         ([ shift = { (\l_tzbezier_shift_coor_tl) } ]#3)
       }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzbezier_cmd_tl { (#2) and (#3) }
     }
     %% end coor
     \bool_if:NTF \l_tzbezier_shift_coor_bool
     {% if shift
       \tl_put_right:Nx \l_tzbezier_cmd_tl
       { .. ([shift = { (\l_tzbezier_shift_coor_tl) } ]#4) }
     }
     {% no shift (normal)
       \tl_put_right:Nn \l_tzbezier_cmd_tl { .. (#4) }
     }
   }
 }

 \tl_put_right:Nn \l_tzbezier_cmd_tl
   { node [ #6 ] { #5 } }
 % add at begin/end
 \bool_if:NT \g_tzbezier_BEGIN_cmd_bool
   { \tl_put_left:Nx \l_tzbezier_cmd_tl { \g_tzbezier_BEGIN_cmd_tl } }
 \bool_if:NT \g_tzbezier_END_cmd_bool
   { \tl_put_right:Nx \l_tzbezier_cmd_tl { \g_tzbezier_END_cmd_tl } }

 % final action
 \tl_put_left:No \l_tzbezier_cmd_tl { \l_tzbezier_opt_tl ] }
 \tl_put_left:Nx \l_tzbezier_cmd_tl
   { [ \l_tzbezier_pathname_tl , }

 \exp_last_unbraced:Nf \draw \l_tzbezier_cmd_tl #7 ;

 \bool_gset_false:N \g_tzbezier_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzbezier_END_cmd_bool
%  \tl_clear:N \g_tzbezier_BEGIN_cmd_tl
%  \tl_clear:N \g_tzbezier_END_cmd_tl
}

%%% -- end of \tzbezier


%%% \tzarc (main)

\use:x{
 \NewDocumentCommand \exp_not:N \tzarc
 { s t' O{} d<> D""{} r()
   >{ \SplitArgument {2} { \tl_to_str:n {:} } } r()
 }
}
{
 \IfBooleanTF { #1 } {}{}  % NOT USED!

 \tl_clear:N \l_tzarc_cmd_tl

 \tzarc_args_process #7
 \fp_set:Nn \l_tmpa_fp { \tzarcAngleA }
 \fp_set:Nn \l_tmpb_fp { \tzarcAngleB }

 \tl_put_right:Nn \l_tzarc_cmd_tl
   { [ name~path = #5 , #3 ] }
 \IfValueTF { #4 }
 {% if shift
   \tl_put_right:Nn \l_tzarc_cmd_tl
   { ([shift={(#4)}]#6) ++ (\tzarcAngleA \c_colon_str \tzarcRadius) }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tzarc_cmd_tl
   { (#6) ++ (\tzarcAngleA \c_colon_str \tzarcRadius) }
 }

 \tl_put_right:Nx \l_tzarc_cmd_tl
   {
     \fp_compare:nTF { \l_tmpa_fp < \l_tmpb_fp }
     {
       arc ( \tzarcAngleA
             \c_colon_str
             \IfBooleanTF { #2 }
               {\tzarcAngleB - 360}
               {\tzarcAngleB}
             \c_colon_str
             \tzarcRadius )
     }
     {
       arc ( \IfBooleanTF { #2 }
               {\tzarcAngleA - 360}
               {\tzarcAngleA}
             \c_colon_str
             \tzarcAngleB
             \c_colon_str
             \tzarcRadius )
     }
   }

 \tzarc_sub_fn:n
}

\NewDocumentCommand\tzarc_args_process{ m m m }
{
 \def\tzarcAngleA{#1}
 \def\tzarcAngleB{#2}
 \def\tzarcRadius{#3}
}

\cs_new:Npn \tzarc_sub_fn:n
{
 \tzarc_final_actions
}

\NewDocumentCommand\tzarc_final_actions{ +G{} O{} D<>{} }
{
 \tl_put_right:Nn \l_tzarc_cmd_tl
   { node [ #2 ] { #1 } #3 }

 \exp_last_unbraced:Nf \draw \l_tzarc_cmd_tl ;
}

%%% --- end of \tzarc


%%% \tzarcfrom (main)
%% (works like tikz original)

\use:x{
 \NewDocumentCommand \exp_not:N \tzarcfrom
 { s t' O{} d<> D""{} r()
   >{ \SplitArgument {2} { \tl_to_str:n {:} } } r()
 }
}
{
 \IfBooleanTF { #1 } {}{}  % NOT USED!

 \tl_clear:N \l_tzarcfrom_cmd_tl

 \tzarcfrom_args_process #7
 \fp_set:Nn \l_tmpa_fp { \tzarcfromAngleA }
 \fp_set:Nn \l_tmpb_fp { \tzarcfromAngleB }

 \tl_put_right:Nn \l_tzarcfrom_cmd_tl
   { [ name~path = #5 , #3 ] }

 \IfValueTF { #4 }
 {% if shift
   \tl_put_right:Nn \l_tzarcfrom_cmd_tl
     { ([shift={(#4)}]#6) }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tzarcfrom_cmd_tl
     { (#6) } % ++ (\tzarcfromAngleA \c_colon_str \tzarcfromRadius)
 }

 \tl_put_right:No \l_tzarcfrom_cmd_tl
   {
     \fp_compare:nTF { \l_tmpa_fp < \l_tmpb_fp }
     {
       arc ( \tzarcfromAngleA
             \c_colon_str
             \IfBooleanTF {#2}
               {\tzarcfromAngleB - 360}
               {\tzarcfromAngleB}
             \c_colon_str
             \tzarcfromRadius )
     }
     {
       arc ( \IfBooleanTF {#2}
               {\tzarcfromAngleA - 360}
               {\tzarcfromAngleA}
             \c_colon_str
             \tzarcfromAngleB
             \c_colon_str
             \tzarcfromRadius )
     }
   }

 \tzarcfrom_sub_fn:n

}

\NewDocumentCommand\tzarcfrom_args_process{ m m m }
{
 \def\tzarcfromAngleA{#1}
 \def\tzarcfromAngleB{#2}
 \def\tzarcfromRadius{#3}
}

\cs_new:Npn \tzarcfrom_sub_fn:n
{
 \tzarcfrom_final_actions
}

\NewDocumentCommand\tzarcfrom_final_actions{ +G{} O{} D<>{} }
{
 \tl_put_right:Nn \l_tzarcfrom_cmd_tl
   { node [ #2 ] { #1 } #3 }
 \exp_last_unbraced:Nf \draw \l_tzarcfrom_cmd_tl ;
}

%%% --- end of \tzarcfrom


%%% \tzarcsfrom (main)
%% (works like tikz original)

\tl_new:N \l_tzarcsfrom_code_at_end_tl

\NewDocumentCommand\tzarcsfrom { s t' O{} d<> D""{} r() }
{
 \IfBooleanTF { #1 } {}{}  % NOT USED!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 }
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \tl_clear:N \l_tzarcsfrom_cmd_tl
 \tl_put_right:Nn \l_tzarcsfrom_cmd_tl
   { [ name~path = #5 , #3 ] }

 \IfValueTF { #4 }
 {% if shift
   \tl_put_right:Nn \l_tzarcsfrom_cmd_tl
     { ([shift={(#4)}]#6) }
 }
 {% no shift
   \tl_put_right:Nn \l_tzarcsfrom_cmd_tl
     { (#6) } % ++ (\tzarcsfromAngleA \c_colon_str \tzarcsfromRadius)
 }

 \tzarcsfrom_check_token:n
}

\cs_new:Npn \tzarcsfrom_check_token:n #1
{
 \str_case:nnF { #1 }
 {
   { ( } { \tzarcsfrom_sub_fn #1 }
   { ; } { \tzarcsfrom_late_opt_fn }
 }
 {
%    \tzarcsfrom_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}


\use:x{
 \NewDocumentCommand \exp_not:N \tzarcsfrom_sub_fn
 { >{ \SplitArgument {2} { \tl_to_str:n {:} } } r() +G{} O{}
 }
}
{
 \tzarcsfrom_args_process #1
 \fp_set:Nn \l_tmpa_fp { \tzarcsfromAngleA }
 \fp_set:Nn \l_tmpb_fp { \tzarcsfromAngleB }

 \tl_put_right:Nx \l_tzarcsfrom_cmd_tl
   {
     \fp_compare:nTF { \l_tmpa_fp < \l_tmpb_fp }
     {
       arc ( \tzarcsfromAngleA
             \c_colon_str
             \bool_if:NTF \l_tmpb_bool
               {\tzarcsfromAngleB - 360}
               {\tzarcsfromAngleB}
             \c_colon_str
             \tzarcsfromRadius )
     }
     {
       arc ( \bool_if:NTF \l_tmpb_bool
               {\tzarcsfromAngleA - 360}
               {\tzarcsfromAngleA}
             \c_colon_str
             \tzarcsfromAngleB
             \c_colon_str
             \tzarcsfromRadius )
     }
   }
 \tl_put_right:Nn \l_tzarcsfrom_cmd_tl
   { node [ #3 ] { #2 } }

 \tzarcsfrom_check_token:n
}

\NewDocumentCommand\tzarcsfrom_late_opt_fn { D<>{} }
{
 \tl_set:Nn \l_tzarcsfrom_code_at_end_tl { #1 }
 \tzarcsfrom_stop_action
}

\NewDocumentCommand\tzarcsfrom_stop_action {}
{
 \tl_put_right:No \l_tzarcsfrom_cmd_tl
   { \l_tzarcsfrom_code_at_end_tl }
 \exp_last_unbraced:Nf \draw \l_tzarcsfrom_cmd_tl ;
}

\NewDocumentCommand\tzarcsfrom_args_process{ m m m }
{
 \def\tzarcsfromAngleA{#1}
 \def\tzarcsfromAngleB{#2}
 \def\tzarcsfromRadius{#3}
}

%%% --- end of \tzarcsfrom


%%% \tzwedge (main)

\use:x{
 \NewDocumentCommand \exp_not:N \tzwedge
 { s t' O{} d<> D""{} r()
   >{ \SplitArgument {2} { \tl_to_str:n {:} } } r()
 }
}
{
 \tl_clear:N \l_tzwedge_cmd_tl

 \tzwedge_args_process #7
 \fp_set:Nn \l_tmpa_fp { \tzwedgeAngleA }
 \fp_set:Nn \l_tmpb_fp { \tzwedgeAngleB }

 \IfBooleanTF { #1 }
 {
   \tl_put_right:Nn \l_tzwedge_cmd_tl
     {
       [ fill=\tzfillcolor ,
         fill~opacity = \tzfillopacity , text~opacity = 1 ,
         name~path = #5 , #3 ]
     }
 }
 {
   \tl_put_right:Nn \l_tzwedge_cmd_tl
     { [ name~path = #5 , #3 ] }
 }

 \IfValueTF { #4 }
 {
   \tl_put_right:Nn \l_tzwedge_cmd_tl
   { ([shift={(#4)}]#6) -- ++ (\tzwedgeAngleA \c_colon_str \tzwedgeRadius) }
 }
 {
   \tl_put_right:Nn \l_tzwedge_cmd_tl
   { (#6) -- ++ (\tzwedgeAngleA \c_colon_str \tzwedgeRadius) }
 }

 \tl_put_right:No \l_tzwedge_cmd_tl
   {
     \fp_compare:nTF { \l_tmpa_fp < \l_tmpb_fp }
     {
       arc ( \tzwedgeAngleA
             \c_colon_str
             \IfBooleanTF {#2}
               {\tzwedgeAngleB - 360}
               {\tzwedgeAngleB}
             \c_colon_str
             \tzwedgeRadius )
     }
     {
       arc ( \IfBooleanTF {#2}
               {\tzwedgeAngleA - 360}
               {\tzwedgeAngleA}
             \c_colon_str
             \tzwedgeAngleB
             \c_colon_str
             \tzwedgeRadius )
     }
   }

 \tzwedge_sub_fn:n
}

\cs_new:Npn \tzwedge_sub_fn:n
{
 \tzwedge_final_actions
}

\NewDocumentCommand\tzwedge_final_actions{ +G{} O{} G{.3} }
{
 \tl_if_empty:nTF { #3 }
 { \renewcommand\tzfillopacity{\tz@initial@fill@opacity} }
 { \renewcommand\tzfillopacity{#3} }

 \tl_put_right:Nn \l_tzwedge_cmd_tl
   {
     node [ midway , #2 ] { #1 }
   }

 \exp_last_unbraced:Nf \draw \l_tzwedge_cmd_tl -- cycle ;
}

\NewDocumentCommand\tzwedge_args_process{ m m m }
{
 \def\tzwedgeAngleA{#1}
 \def\tzwedgeAngleB{#2}
 \def\tzwedgeRadius{#3}
}

%%% --- end of \tzwedge


%%%%% Angles


%%% \tzp

\NewDocumentCommand\tzpointangle{ r() r() m }
{
 \pgfmathanglebetweenpoints{\pgfpointanchor{#1}{center}}%
                           {\pgfpointanchor{#2}{center}}
 \edef#3{\pgfmathresult}
%  \tl_set:cx { #3 } { \pgfmathresult }
}



%%% \tzanglemark (main)

\NewDocumentCommand\tzanglemark{ s t' o }
{
 \tl_clear:N \l_tzanglemark_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 }
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzanglemark_opt_tl { #3 } }
 { \tl_clear:N \l_tzanglemark_opt_tl }

 \tzanglemark_check_token:n
}

\cs_new:Npn \tzanglemark_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzanglemark_sub_fn ( }
}

\NewDocumentCommand\tzanglemark_sub_fn
 { r() r() r() +G{} O{}
   D(){\tz@initial@AA@radius} G{\tz@initial@fill@opacity}
 }

{
 \renewcommand\tzfillopacity{#7}
 \renewcommand\tzAAradius{#6}

 \path (#1) coordinate (tzAng-A)
       (#2) coordinate (tzAng-B)
       (#3) coordinate (tzAng-C);
 \pgfmathanglebetweenpoints{\pgfpointanchor{tzAng-B}{center}}%
                           {\pgfpointanchor{tzAng-A}{center}}
 \edef\tzangleONE{\pgfmathresult}
 \pgfmathanglebetweenpoints{\pgfpointanchor{tzAng-B}{center}}%
                           {\pgfpointanchor{tzAng-C}{center}}
 \edef\tzangleTWO{\pgfmathresult}

 \fp_set:Nn \l_tmpa_fp { \tzangleONE }
 \fp_set:Nn \l_tmpb_fp { \tzangleTWO }

 \bool_if:NTF \l_tmpb_bool
 {
   \edef\tzangleresult{\fp_eval:n { 360 - abs(\l_tmpb_fp - \l_tmpa_fp) } }
 }
 {
   \edef\tzangleresult{\fp_eval:n { abs(\l_tmpb_fp - \l_tmpa_fp) } }
 }

%  % test
%  \node (0,0) [align=left,right] {\tzangleresult \\ \halfangle};

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_right:No \l_tzanglemark_cmd_tl
   {
     [ \tzAAlinestyle , draw = none , fill = \tzfillcolor ,
       fill~opacity = \tzfillopacity , text~opacity = 1 ,
   }
 }
 {
   \tl_put_right:No \l_tzanglemark_cmd_tl
   {
     [ \tzAAlinestyle ,
   }
 }

 \tl_put_right:No \l_tzanglemark_cmd_tl
 {     \l_tzanglemark_opt_tl ] }

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_right:Nx \l_tzanglemark_cmd_tl
   { (#2) -- ++ (\tzangleONE \c_colon_str #6) }
 }
 {
   \tl_put_right:Nx \l_tzanglemark_cmd_tl
   { (#2)    ++ (\tzangleONE \c_colon_str #6) }
 }

 \tl_put_right:Nx \l_tzanglemark_cmd_tl
 {
   \fp_compare:nTF { \l_tmpa_fp < \l_tmpb_fp }
   {
     arc ( \tzangleONE
           \c_colon_str
           \bool_if:NTF \l_tmpb_bool
             { \tzangleTWO - 360 }
             { \tzangleTWO }
           \c_colon_str
           \tzAAradius ) node (tzAAmid) [midway] {}
   }
   {
     arc ( \bool_if:NTF \l_tmpb_bool
             { \tzangleONE -360 }
             { \tzangleONE }
           \c_colon_str
           \tzangleTWO
           \c_colon_str
           \tzAAradius ) node (tzAAmid) [midway] {}
   }
 }

 \begin{pgfonlayer}{\tzanglelayer}
 \bool_if:NTF \l_tmpa_bool
 {
   \exp_last_unbraced:Nf
     \draw \l_tzanglemark_cmd_tl -- cycle ; %% -- cycle
 }
 {
   \exp_last_unbraced:Nf
     \draw \l_tzanglemark_cmd_tl ;
 }
 \end{pgfonlayer}

 \path (#2) -- (tzAAmid.center) node [ pos = 1.5, #5 ] { #4 } ;
}

%%% --- end of \tzanglemark


%%% \tzanglefill (obsolete: to be removed)

\NewDocumentCommand\tzanglefill{ s t' o }
{
 \tl_clear:N \l_tzanglefill_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 }
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzanglefill_opt_tl { #3 } }
 { \tl_clear:N \l_tzanglefill_opt_tl }

 \tzanglefill_check_token:n
}

\cs_new:Npn \tzanglefill_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzanglefill_sub_fn ( }
}

\NewDocumentCommand\tzanglefill_sub_fn
 { r() r() r() +G{} O{} D(){10pt} G{\tz@initial@fill@opacity} }

{
 \renewcommand\tzfillopacity{#7}

 \path (#1) coordinate (tzAng-A)
       (#2) coordinate (tzAng-B)
       (#3) coordinate (tzAng-C);
 \pgfmathanglebetweenpoints{\pgfpointanchor{tzAng-B}{center}}%
                           {\pgfpointanchor{tzAng-A}{center}}
 \edef\tzangleONE{\pgfmathresult}
 \pgfmathanglebetweenpoints{\pgfpointanchor{tzAng-B}{center}}%
                           {\pgfpointanchor{tzAng-C}{center}}
 \edef\tzangleTWO{\pgfmathresult}

 \fp_set:Nn \l_tmpa_fp { \tzangleONE }
 \fp_set:Nn \l_tmpb_fp { \tzangleTWO }

 \bool_if:NTF \l_tmpb_bool
 {
   \edef\tzangleresult{\fp_eval:n { 360 - abs(\l_tmpb_fp - \l_tmpa_fp) } }
 }
 {
   \edef\tzangleresult{\fp_eval:n { abs(\l_tmpb_fp - \l_tmpa_fp) } }
 }

%  % test
%  \node (0,0) [align=left,right] {\tzangleresult};

 \bool_if:NTF \l_tmpa_bool %%% (* NOT USED!)
 {
   \tl_put_right:No \l_tzanglefill_cmd_tl
   {
     [ \tzAAlinestyle , fill = \tzfillcolor ,
       fill~opacity = \tzfillopacity , text~opacity = 1 ,
   }
 }
 {
   \tl_put_right:No \l_tzanglefill_cmd_tl
   {
     [ \tzAAlinestyle , fill = \tzfillcolor ,
       fill~opacity = \tzfillopacity , text~opacity = 1 ,
   }
 }

 \tl_put_right:No \l_tzanglefill_cmd_tl
 {     \l_tzanglefill_opt_tl ] }

 \tl_put_right:Nx \l_tzanglefill_cmd_tl
 { (#2) -- ++ (\tzangleONE \c_colon_str #6) }

 \tl_put_right:Nx \l_tzanglefill_cmd_tl
 {
   \fp_compare:nTF { \l_tmpa_fp < \l_tmpb_fp }
   {
     arc ( \tzangleONE
           \c_colon_str
           \bool_if:NTF \l_tmpb_bool
             { \tzangleTWO - 360 }
             { \tzangleTWO }
           \c_colon_str
           #6 ) node (tzAAmid) [midway] {}
   }
   {
     arc ( \bool_if:NTF \l_tmpb_bool
             { \tzangleONE -360 }
             { \tzangleONE }
           \c_colon_str
           \tzangleTWO
           \c_colon_str
           #6 ) node (tzAAmid) [midway] {}
   }
 }

 \begin{pgfonlayer}{\tzanglelayer}
 \exp_last_unbraced:Nf
   \path \l_tzanglefill_cmd_tl -- cycle ; %% -- cycle
 \end{pgfonlayer}
 \path (#2) -- (tzAAmid.center) node [ pos = 1.5, #5 ] { #4 } ;
}

%%% --- end of \tzanglefill




%%%(ADDED)
%%% \tzrightanglemark (main)

\NewDocumentCommand\tzrightanglemark{ s t' o }
{
 \tl_clear:N \l_tzrightanglemark_cmd_tl
 \tl_clear:N \l_tzrightanglemark_fill_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % NOT USED (just to avoid frequent coding error)
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzrightanglemark_opt_tl { #3 } }
 { \tl_clear:N \l_tzrightanglemark_opt_tl }

 \tzrightanglemark_check_token:n
}

\cs_new:Npn \tzrightanglemark_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzrightanglemark_sub_fn ( }
}

\NewDocumentCommand\tzrightanglemark_sub_fn
 { r() r() r() +G{} O{} D(){\tz@initial@RA@size} G{\tz@initial@fill@opacity} }

{
 \renewcommand\tzfillopacity{#7}
 \renewcommand\tzRAsize{#6}

 \coordinate (tzRAOne) at ($(#2)!\tzRAsize!(#1)$) ;
 \coordinate (tzRAThree) at ($(#2)!\tzRAsize!(#3)$) ;
 \coordinate (tzRAvertex) at ($(tzRAThree) + (tzRAOne) - (#2)$) ;

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_right:No \l_tzrightanglemark_cmd_tl
   {
     [ \tzAAlinestyle , draw = none ,
       fill = \tzfillcolor , fill~opacity = \tzfillopacity , text~opacity = 1 ,
   }
 }
 {
   \tl_put_right:No \l_tzrightanglemark_cmd_tl
   {
     [ \tzAAlinestyle ,
   }
 }

 \tl_put_right:No \l_tzrightanglemark_cmd_tl
 { \l_tzrightanglemark_opt_tl ] }

 \begin{pgfonlayer}{\tzanglelayer}
 \bool_if:NTF \l_tmpa_bool
 {
   \exp_last_unbraced:Nf
     \draw \l_tzrightanglemark_cmd_tl
       (#2) -- (tzRAOne) -- (tzRAvertex) -- (tzRAThree) -- cycle ;
 }
 {
   \exp_last_unbraced:Nf
     \draw \l_tzrightanglemark_cmd_tl
       (tzRAOne) -- (tzRAvertex) -- (tzRAThree) ;
 }
 \end{pgfonlayer}
 \path (#2) -- (tzRAvertex) node [ pos = 2 , #5 ] { #4 } ;
}

%%% --- end of \tzrightanglemark


%%% \tzrightanglefill (obsolete: to be removed)

\NewDocumentCommand\tzrightanglefill{ s t' o }
{
 \tl_clear:N \l_tzrightanglefill_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 }
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzrightanglefill_opt_tl { #3 } }
 { \tl_clear:N \l_tzrightanglefill_opt_tl }

 \tzrightanglefill_check_token:n
}

\cs_new:Npn \tzrightanglefill_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzrightanglefill_sub_fn ( }
}

\NewDocumentCommand\tzrightanglefill_sub_fn
 { r() r() r() +G{} O{} D(){5pt} G{\tz@initial@fill@opacity} }

{
 \renewcommand\tzfillopacity{#7}

 \coordinate (tzRAOne) at ($(#2)!#6!(#1)$) ;
 \coordinate (tzRAThree) at ($(#2)!#6!(#3)$) ;
 \coordinate (tzRAvertex) at ($(tzRAThree) + (tzRAOne) - (#2)$) ;

 \tl_put_right:Nn \l_tzrightanglefill_cmd_tl
 {
   [ very~thin ,
 }

 \tl_put_right:Nn \l_tzrightanglefill_cmd_tl
 {
     fill = \tzfillcolor , fill~opacity = \tzfillopacity , text~opacity = 1 ,
 }

 \tl_put_right:No \l_tzrightanglefill_cmd_tl
 { \l_tzrightanglefill_opt_tl ] }

 \begin{pgfonlayer}{\tzanglelayer}
 \exp_last_unbraced:Nf
   \fill \l_tzrightanglefill_cmd_tl
     (#2) -- (tzRAOne) -- (tzRAvertex) -- (tzRAThree) -- cycle ;
 \end{pgfonlayer}
 \path (#2) -- (tzRAvertex) node [ pos = 2 , #5 ] { #4 } ;
}

%%% --- end of \tzrightanglefill



%%%(ADDED)
%%% \tzpicangle (to be removed)
\NewDocumentCommand\tzpicangle
 { t' O{} O{} r() r() r() G{} O{1.5} D(){10pt} }
{
 \IfBooleanTF #1
 {
    \begin{pgfonlayer}{background}
    \path [ #3 ] (#4) coordinate (tzangleA) --
                (#5) coordinate (tzangleB) --
                (#6) coordinate (tzangleC)
     pic [ draw , "#7" , angle~radius=#9 , angle~eccentricity = #8 , #2 ]
        { angle  = tzangleC -- tzangleB -- tzangleA } ;
        % C to A (counter clockwise)
   \end{pgfonlayer}
 }
 {
    \begin{pgfonlayer}{background}
    \path [ #3 ] (#4) coordinate (tzangleA) --
                (#5) coordinate (tzangleB) --
                (#6) coordinate (tzangleC)
     pic [ draw , "#7" , angle~radius=#9 , angle~eccentricity = #8 , #2 ]
        { angle = tzangleA -- tzangleB -- tzangleC } ;
        % A to C (clockwise)
   \end{pgfonlayer}
 }
}

%%% --- end of \tzpicangle



%%%%% plot coordinates (of TikZ)


%%% \tzplot

\bool_new:N \l_tzplot_shift_coor_bool
\bool_new:N \g_tzplot_BEGIN_cmd_bool
\bool_new:N \g_tzplot_END_cmd_bool

%% \tzplotAtBegin
\NewDocumentCommand\tzplotAtBegin{ m }
{
 \bool_gset_true:N \g_tzplot_BEGIN_cmd_bool
 \tl_gset:No \g_tzplot_BEGIN_cmd_tl { #1 }
}

%% \tzplotAtEnd
\NewDocumentCommand\tzplotAtEnd{ m }
{
 \bool_gset_true:N \g_tzplot_END_cmd_bool
 \tl_gset:No \g_tzplot_END_cmd_tl { #1 }
}

%%% \tzplot (main)
\NewDocumentCommand\tzplot{ s O{} G{0} O{} d<> D""{} }
{
 \tl_clear:N \l_tzplot_opt_tl              % [opt]
 \tl_clear:N \l_tzplot_TEMP_opt_tl         % for path only: [opt,mark=none]
 \tl_clear:N \l_tzplot_plot_coordinates_tl % plot coordinates
 \tl_clear:N \l_tzplot_coors_tl            % {(coor-1)(coor-2)...(coor-n)}
 \tl_clear:N \l_tzplot_code_at_end_tl      % <code.append>
 \tl_clear:N \l_tzplot_nodes_tl

 \renewcommand\tzmarksize{\tz@initial@mark@size}

 \tl_put_right:Nn \l_tzplot_opt_tl
 {
   [
     name~path = #6 ,
     tension = #3 ,
     smooth ,
     tzmark = \tzmarksize ,
 }

 %% closing options
 % if AtBegin_true, USE mark=none (for path only)
 \bool_if:NT \g_tzplot_BEGIN_cmd_bool
 {
   \tl_set_eq:NN \l_tzplot_TEMP_opt_tl \l_tzplot_opt_tl
   \tl_put_right:Nn \l_tzplot_TEMP_opt_tl { mark = none ] }
 }
 % (normal)
 \IfBooleanTF { #1 }
 {
   \tl_put_right:Nn \l_tzplot_opt_tl
   { mark = * , draw = none , #2 ] }
 }
 {
   \tl_put_right:Nn \l_tzplot_opt_tl
   {                          #2 ] }
 }
 \IfValueTF { #5 }
 {
   \tl_set:Nn \l_tzplot_shift_coor_tl { #5 }
   \bool_set_true:N \l_tzplot_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzplot_shift_coor_tl
   \bool_set_false:N \l_tzplot_shift_coor_bool
 }

 \tl_put_right:Nn \l_tzplot_plot_coordinates_tl
 { plot [ #4 ] coordinates }
 \tzplot_check_token:n
}

\cs_new:Npn \tzplot_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzplot_sub_fn #1 }
%  { \tzplot_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzplot_sub_fn #1 }
   { ; } { \tzplot_late_opt_fn }
 }
 {
%    \tzplot_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzplot_sub_fn{ r() +G{} >{\TrimSpaces}o }
{
%%%%%% to use string replacement for label positions
 \IfValueTF { #3 }
 {
       \tl_if_in:nnTF { #3 } { [ }
   { \extract_posopt:w #3 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #3 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #3 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%
 % collect coordinates only
 \bool_if:NTF \l_tzplot_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzplot_coors_tl
   { ( [ shift = { (\l_tzplot_shift_coor_tl) } ] \exp_not:n { #1 } ) }
 }
 {
   \tl_put_right:Nn \l_tzplot_coors_tl { (#1) }
 }
 % collect nodes information
 \bool_if:NTF \l_tzplot_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzplot_nodes_tl
   { ( [ shift = { (\l_tzplot_shift_coor_tl) } ] \exp_not:n { #1 } ) }
 }
 {
   \tl_put_right:Nn \l_tzplot_nodes_tl { (#1) }
 }
 \tl_put_right:Nx \l_tzplot_nodes_tl
 {
   node
   [ label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #2 } } % pos_str
   ] {}
 }
 \tzplot_check_token:n
}

\NewDocumentCommand\tzplot_late_opt_fn { d() D<>{} }
{
 \IfValueTF { #1 }
   { \edef\tztmpMarkSize { #1 } }
   { \edef\tztmpMarkSize { \tz@initial@mark@size } }
 \tl_put_right:Nn \l_tzplot_code_at_end_tl { #2 }
 \tzplot_stop_action
}

\NewDocumentCommand\tzplot_stop_action {}
{
 \renewcommand\tzmarksize{ \tztmpMarkSize }
 %% final action cases:
 \bool_if:NTF \g_tzplot_BEGIN_cmd_bool
 { %% if AtBegin_true
    % define (tzCSPS) by path (WITH \l_tzplot_TEMP_opt_tl )
    \exp_last_unbraced:Nf
      \path
        \l_tzplot_TEMP_opt_tl
        \l_tzplot_plot_coordinates_tl
        { \l_tzplot_coors_tl }
      ;
    \path (current~subpath~start) coordinate (tzCSPS) ;
    % all together (important)
    \tl_clear:N \l_tmpa_tl % (2022/08/31 ndh)
    \tl_put_right:No \l_tmpa_tl { \g_tzplot_BEGIN_cmd_tl }
    \tl_put_right:Nn \l_tmpa_tl { (tzCSPS) -- }
    \tl_put_right:No \l_tmpa_tl { \l_tzplot_plot_coordinates_tl } % important
    \bool_if:NTF \g_tzplot_END_cmd_bool
    { %% if AtEnd_true
      % append AtBegin, AtEnd
      % plot AtBegin, (coors), and AtEnd (WITH \l_tzplot_opt_tl)
      \exp_last_unbraced:Nf
        \draw
          \l_tzplot_opt_tl
          \l_tmpa_tl                          % AtBegin + plot coordinates
          { \l_tzplot_coors_tl }
          \g_tzplot_END_cmd_tl                % AtEnd
          \l_tzplot_code_at_end_tl
          \l_tzplot_nodes_tl
        ;
    }
    { %% if AtEnd_false
      % plot AtBegin and (coors)
      \exp_last_unbraced:Nf
        \draw
          \l_tzplot_opt_tl
          \l_tmpa_tl                          % AtBegin + plot coordinates
          { \l_tzplot_coors_tl }
%           \g_tzplot_END_cmd_tl               % AtEnd
          \l_tzplot_code_at_end_tl
          \l_tzplot_nodes_tl
        ;

    }
 }
 { %% if AtBegin_false
    \bool_if:NTF \g_tzplot_END_cmd_bool
    { %% if AtEnd_true
      % append AtBegin, AtEnd
      % plot AtBegin, (coors), and AtEnd (WITH \l_tzplot_opt_tl)
      \exp_last_unbraced:Nf
        \draw
          \l_tzplot_opt_tl
          \l_tzplot_plot_coordinates_tl
          { \l_tzplot_coors_tl }
          \g_tzplot_END_cmd_tl                % AtEnd
          \l_tzplot_code_at_end_tl
          \l_tzplot_nodes_tl
        ;
    }
    { %% if AtEnd_false
      % normal
      \exp_last_unbraced:Nf
        \draw
          \l_tzplot_opt_tl                    % [opt]
          \l_tzplot_plot_coordinates_tl       % plot coordinates
          { \l_tzplot_coors_tl }              % { (coor-1)(coor-2)...(coor-n) }
%           \g_tzplot_END_cmd_tl               % AtEnd
          \l_tzplot_code_at_end_tl            % <code.append>
          \l_tzplot_nodes_tl                  % (coor-i) node [opt] {text}, all i
        ;
    }
 }

 \bool_gset_false:N \g_tzplot_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzplot_END_cmd_bool
}

%%% --- end of \tzplot


%%% \tzplotcurve

\bool_new:N \l_tzplotcurve_shift_coor_bool
\bool_new:N \g_tzplotcurve_BEGIN_cmd_bool
\bool_new:N \g_tzplotcurve_END_cmd_bool

%% \tzplotcurveAtBegin
\NewDocumentCommand\tzplotcurveAtBegin{ m }
{
 \bool_gset_true:N \g_tzplotcurve_BEGIN_cmd_bool
 \tl_gset:No \g_tzplotcurve_BEGIN_cmd_tl { #1 }
}

%% \tzplotcurveAtEnd
\NewDocumentCommand\tzplotcurveAtEnd{ m }
{
 \bool_gset_true:N \g_tzplotcurve_END_cmd_bool
 \tl_gset:No \g_tzplotcurve_END_cmd_tl { #1 }
}


%%% \tzplotcurve (main)
\NewDocumentCommand\tzplotcurve{ s O{} G{1} O{} d<> D""{} }
{
 \tl_clear:N \l_tzplotcurve_opt_tl              % [opt]
 \tl_clear:N \l_tzplotcurve_TEMP_opt_tl         % for path only: [opt,mark=none]
 \tl_clear:N \l_tzplotcurve_plot_coordinates_tl % plot coordinates
 \tl_clear:N \l_tzplotcurve_coors_tl            % {(coor-1)(coor-2)...(coor-n)}
 \tl_clear:N \l_tzplotcurve_code_at_end_tl      % <code.append>
 \tl_clear:N \l_tzplotcurve_nodes_tl

 \renewcommand\tzmarksize{\tz@initial@mark@size}

 \tl_put_right:Nn \l_tzplotcurve_opt_tl
 {
   [ name~path = #6 ,
     tension = #3 ,
     smooth ,
     tzmark = \tzmarksize ,
 }

 %% closing options
 % if AtBegin_true, USE mark=none (for path only)
 \bool_if:NT \g_tzplotcurve_BEGIN_cmd_bool
 {
   \tl_set_eq:NN \l_tzplotcurve_TEMP_opt_tl \l_tzplotcurve_opt_tl
   \tl_put_right:Nn \l_tzplotcurve_TEMP_opt_tl { mark = none ] }
 }
 % (normal)
 \IfBooleanTF { #1 }
 {
   \tl_put_right:Nn \l_tzplotcurve_opt_tl { mark = * , #2 ] }
 }
 {
   \tl_put_right:Nn \l_tzplotcurve_opt_tl {            #2 ] }
 }

 \IfValueTF { #5 }
 {
   \tl_set:Nn \l_tzplotcurve_shift_coor_tl { #5 }
   \bool_set_true:N \l_tzplotcurve_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzplotcurve_shift_coor_tl
   \bool_set_false:N \l_tzplotcurve_shift_coor_bool
 }

 \tl_put_right:Nn \l_tzplotcurve_plot_coordinates_tl
   { plot [ #4 ] coordinates }
 \tzplotcurve_check_token:n
}

\cs_new:Npn \tzplotcurve_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzplotcurve_sub_fn #1 }
%  { \tzplotcurve_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzplotcurve_sub_fn #1 }
   { ; } { \tzplotcurve_late_opt_fn }
 }
 {
%    \tzplotcurve_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzplotcurve_sub_fn{ r() +G{} >{\TrimSpaces}o }
{
%%%%%% to use string replacement for label positions
 \IfValueTF { #3 }
 {
       \tl_if_in:nnTF { #3 } { [ }
   { \extract_posopt:w #3 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #3 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #3 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%
 % collect coordinates only
 \bool_if:NTF \l_tzplotcurve_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzplotcurve_coors_tl
   { ( [ shift = { (\l_tzplotcurve_shift_coor_tl) } ] \exp_not:n { #1 } ) }
 }
 {
   \tl_put_right:Nn \l_tzplotcurve_coors_tl { (#1) }
 }
 % collect nodes information
 \bool_if:NTF \l_tzplotcurve_shift_coor_bool
 {
   \tl_put_right:Nx \l_tzplotcurve_nodes_tl
   { ( [ shift = { (\l_tzplotcurve_shift_coor_tl) } ] \exp_not:n { #1 } ) }
 }
 {
   \tl_put_right:Nn \l_tzplotcurve_nodes_tl { (#1) }
 }
 \tl_put_right:Nx \l_tzplotcurve_nodes_tl
   { node
     [ label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #2 } } % pos_str
     ] {}
   }
 \tzplotcurve_check_token:n
}

\NewDocumentCommand\tzplotcurve_late_opt_fn { d() D<>{} }
{
 \IfValueTF { #1 }
   { \edef\tztmpMarkSize { #1 } }
   { \edef\tztmpMarkSize { \tz@initial@mark@size } }
 \tl_put_right:Nn \l_tzplotcurve_code_at_end_tl { #2 }
 \tzplotcurve_stop_action
}

\NewDocumentCommand\tzplotcurve_stop_action {}
{
 \renewcommand\tzmarksize{ \tztmpMarkSize }
 %% final action cases:
 \bool_if:NTF \g_tzplotcurve_BEGIN_cmd_bool
 { %% if AtBegin_true
    % define (tzCSPS) by path (WITH \l_tzplotcurve_TEMP_opt_tl )
    \exp_last_unbraced:Nf
      \path
        \l_tzplotcurve_TEMP_opt_tl
        \l_tzplotcurve_plot_coordinates_tl
        { \l_tzplotcurve_coors_tl }
      ;
    \path (current~subpath~start) coordinate (tzCSPS) ;
    % all together (important)
    \tl_clear:N \l_tmpa_tl % (2022/08/31 ndh)
    \tl_put_right:No \l_tmpa_tl { \g_tzplotcurve_BEGIN_cmd_tl }
    \tl_put_right:Nn \l_tmpa_tl { (tzCSPS) -- }
    \tl_put_right:No \l_tmpa_tl { \l_tzplotcurve_plot_coordinates_tl } % important
    \bool_if:NTF \g_tzplotcurve_END_cmd_bool
    { %% if AtEnd_true
      % append AtBegin, AtEnd
      % plot AtBegin, (coors), and AtEnd (WITH \l_tzplotcurve_opt_tl)
      \exp_last_unbraced:Nf
        \draw
          \l_tzplotcurve_opt_tl
          \l_tmpa_tl                              % AtBegin + plot coordinates
          { \l_tzplotcurve_coors_tl }
          \g_tzplotcurve_END_cmd_tl               % AtEnd
          \l_tzplotcurve_code_at_end_tl
          \l_tzplotcurve_nodes_tl
        ;
    }
    { %% if AtEnd_false
      % plot AtBegin and (coors)
      \exp_last_unbraced:Nf
        \draw
          \l_tzplotcurve_opt_tl
          \l_tmpa_tl                             % AtBegin + plot coordinates
          { \l_tzplotcurve_coors_tl }
%           \g_tzplotcurve_END_cmd_tl             % AtEnd
          \l_tzplotcurve_code_at_end_tl
          \l_tzplotcurve_nodes_tl
        ;

    }
 }
 { %% if AtBegin_false
    \bool_if:NTF \g_tzplotcurve_END_cmd_bool
    { %% if AtEnd_true
      % append AtBegin, AtEnd
      % plot AtBegin, (coors), and AtEnd (WITH \l_tzplotcurve_opt_tl)
      \exp_last_unbraced:Nf
        \draw
          \l_tzplotcurve_opt_tl
          \l_tzplotcurve_plot_coordinates_tl
          { \l_tzplotcurve_coors_tl }
          \g_tzplotcurve_END_cmd_tl             % AtEnd
          \l_tzplotcurve_code_at_end_tl
          \l_tzplotcurve_nodes_tl
        ;
    }
    { %% if AtEnd_false
      % normal
      \exp_last_unbraced:Nf
        \draw
          \l_tzplotcurve_opt_tl                 % [opt]
          \l_tzplotcurve_plot_coordinates_tl    % plot coordinates
          { \l_tzplotcurve_coors_tl }           % { (coor-1)(coor-2)...(coor-n) }
%           \g_tzplotcurve_END_cmd_tl            % AtEnd
          \l_tzplotcurve_code_at_end_tl         % <code.append>
          \l_tzplotcurve_nodes_tl               % (coor-i) node [opt] {text}, all i
        ;
    }
 }

 \bool_gset_false:N \g_tzplotcurve_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzplotcurve_END_cmd_bool
}

%%% --- end of \tzplotcurve


%%(ADDED)
%%% \tzplotfile
\NewDocumentCommand\tzplotfile{ O{} m O{} }
{
 \draw [ #1 ] plot [ smooth , #3 ] file { #2 } ;
}

%%% --- end of \tzplotfile


%%%%% Plot functions

%%% \tzdeffn
\NewDocumentCommand\tzdeffn{ m m }
{
 \tl_set:cn { #1 } { #2 }
}
%% USAGE: \tzdeffn{Fx}{2*\x+1}

%%% \tzdeffnofy
\NewDocumentCommand\tzdeffnofy{ m m }
{
 \tl_set:cn { #1 } { #2 }
}
%% just a reminder of using \y instead of \x
%% USAGE: \tzdeffn'{Gy}{2*\y+1}


%%% \tzdefLFn
\NewDocumentCommand\tzdefLFn{ m r() d() G{1} }
{
 \IfNoValueTF { #3 }
 {
   \tzgetxyval(#2){\tzdefLFnXvalS}{\tzdefLFnYvalS}
   \def#1{#4*(\x-\tzdefLFnXvalS)+\tzdefLFnYvalS}
 }
 {
   \tzgetxyval(#2){\tzdefLFnXval}{\tzdefLFnYval}
   \tzgetxyval(#3){\tzdefLFnXXval}{\tzdefLFnYYval}
   \fp_compare:nT { \tzdefLFnXXval - \tzdefLFnXval = 0 }
     { \msg_error:nn { tzplot } { infinite~slope~error } }
   \edef\tzdefLFnSlope{%
     (\tzdefLFnYYval-\tzdefLFnYval)/(\tzdefLFnXXval-\tzdefLFnXval)
   }
   \def#1{\tzdefLFnSlope*(\x-\tzdefLFnXval)+\tzdefLFnYval}
 }
}

%%% \tzdefLFnofy
\NewDocumentCommand\tzdefLFnofy{ m r() d() G{1} }
{ % linear function of \y
 \IfNoValueTF { #3 }
 {
   \tzgetxyval(#2){\tzdefLFnofyXvalS}{\tzdefLFnofyYvalS}
   \def#1{#4*(\y-\tzdefLFnofyYvalS)+\tzdefLFnofyXvalS}
 }
 {
   \tzgetxyval(#2){\tzdefLFnofyXval}{\tzdefLFnofyYval}
   \tzgetxyval(#3){\tzdefLFnofyXXval}{\tzdefLFnofyYYval}
   \fp_compare:nT { \tzdefLFnofyYYval - \tzdefLFnofyYval = 0 }
     { \msg_error:nn { tzplot } { infinite~slope~error } }
   \edef\tzdefLFnofySlope{%
     (\tzdefLFnofyXXval-\tzdefLFnofyXval)/(\tzdefLFnofyYYval-\tzdefLFnofyYval)
   }
   \def#1{\tzdefLFnofySlope*(\y-\tzdefLFnofyYval)+\tzdefLFnofyXval}
 }
}



%%% \tzLFn  -- plot Linear Function (LF)

\bool_new:N \g_tzLFn_BEGIN_cmd_bool
\bool_new:N \g_tzLFn_END_cmd_bool

%% \tzLFnAtBegin
\NewDocumentCommand\tzLFnAtBegin{ m }
{
 \bool_gset_true:N \g_tzLFn_BEGIN_cmd_bool
 \tl_gset:No \g_tzLFn_BEGIN_cmd_tl { #1 }
}

%% \tzLFnAtEnd
\NewDocumentCommand\tzLFnAtEnd{ m }
{
 \bool_gset_true:N \g_tzLFn_END_cmd_bool
 \tl_gset:No \g_tzLFn_END_cmd_tl { #1 }
}

%%% \tzLFn (main)
%% \tzLFn :  variable = \x (default)

\NewDocumentCommand \tzLFn { t' o D<>{0,0} d"" }
{
 \tl_clear:N \l_tzLFn_opt_tl
 \tl_clear:N \l_tzLFn_path_tl
 \tl_clear:N \l_tzLFn_TEMP_cmd_tl
 \tl_clear:N \l_tzLFn_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzLFn_shift_tl
   { shift = { (#3) } }
 }
 { \tl_clear:N \l_tzLFn_shift_tl }

 \IfValueTF { #2 }
 { \tl_set:Nn \l_tzLFn_user_opt_tl { #2 } }
 { \tl_clear:N \l_tzLFn_user_opt_tl }

 \IfValueTF { #4 }
 { \tl_set:Nn \l_tzLFn_namepath_tl { name~path = #4 } }
 { \tl_clear:N \l_tzLFn_namepath_tl }

 \tzLFn_check_token:n
}

\cs_new:Npn \tzLFn_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzLFn_sub_fn ( }
}

\use:x{
 \NewDocumentCommand \exp_not:N \tzLFn_sub_fn
 { r() d() G{1}
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] + G{} O{} D<>{}
 }
}
{
 \tzLFn_domain_process #4

 \tl_put_right:Nx \l_tzLFn_opt_tl
   {
     [
%        samples = 201 ,
       \l_tzLFn_namepath_tl ,
       domain = \tzLFnFromVal \c_colon_str \tzLFnToVal , %%% [here?]
%        variable = \exp_not:n { \x } ,
       \l_tzLFn_shift_tl ,
   }
 \tl_put_right:No \l_tzLFn_opt_tl
   {
       \l_tzLFn_user_opt_tl
     ]
   }

 % define LF: (X,Y)(XX,YY){slope num: dY/dX}
 \IfNoValueTF { #2 }
 {
   \tzgetxyval(#1){\tzLFnXvalS}{\tzLFnYvalS}
   \def\tzLFnDEF{#3*(\x-\tzLFnXvalS)+\tzLFnYvalS}
 }
 {
   \tzgetxyval(#1){\tzLFnXval}{\tzLFnYval}
   \tzgetxyval(#2){\tzLFnXXval}{\tzLFnYYval}
   \fp_compare:nT { \tzLFnXXval - \tzLFnXval = 0 }
     { \msg_error:nn { tzplot } { infinite~slope~error } }
   \edef\tzLFSlope{(\tzLFnYYval-\tzLFnYval)/(\tzLFnXXval-\tzLFnXval)}
   \def\tzLFnDEF{\tzLFSlope*(\x-\tzLFnXval)+\tzLFnYval}
 }

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_right:Nn \l_tzLFn_path_tl
     { plot ( { \tzLFnDEF } , \x ) }  % \x should not be expanded
 }
 {
   \tl_put_right:Nn \l_tzLFn_path_tl
     { plot ( \x , { \tzLFnDEF } ) }  % \x should not be expanded
 }
 % to resolve AtBegin issue with "plot" operation
 \bool_if:NTF \g_tzLFn_BEGIN_cmd_bool
   {
     \tl_put_right:No \l_tzLFn_TEMP_cmd_tl { \l_tzLFn_opt_tl }
     \tl_put_right:No \l_tzLFn_TEMP_cmd_tl { \l_tzLFn_path_tl }
     \exp_last_unbraced:Nf \path \l_tzLFn_TEMP_cmd_tl ;
     \path (current~subpath~start) coordinate (tzCSPS) ;
     \tl_put_right:No \l_tzLFn_cmd_tl { \l_tzLFn_opt_tl }
     \tl_put_right:No \l_tzLFn_cmd_tl { \g_tzLFn_BEGIN_cmd_tl } % insert
     \tl_put_right:Nn \l_tzLFn_cmd_tl { (tzCSPS) -- }           %
     \tl_put_right:No \l_tzLFn_cmd_tl { \l_tzLFn_path_tl }
   }
   {
     \tl_put_right:No \l_tzLFn_cmd_tl { \l_tzLFn_opt_tl }
     \tl_put_right:No \l_tzLFn_cmd_tl { \l_tzLFn_path_tl }
   }
 \bool_if:NT \g_tzLFn_END_cmd_bool
   {
     \tl_put_right:No \l_tzLFn_cmd_tl { \g_tzLFn_END_cmd_tl }   % append
   }
 \tl_put_right:Nn \l_tzLFn_cmd_tl
   { node [ #6 ] { #5 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzLFn_cmd_tl #7 ;

 \bool_gset_false:N \g_tzLFn_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzLFn_END_cmd_bool
}

\NewDocumentCommand\tzLFn_domain_process{ m m }
{
 \def\tzLFnFromVal{#1}
 \def\tzLFnToVal{#2}
}

%%% --- end of \tzLFn



%%% \tzLFnofy
%% variable = \y

\bool_new:N \g_tzLFnofy_BEGIN_cmd_bool
\bool_new:N \g_tzLFnofy_END_cmd_bool

%% \tzLFnofyAtBegin
\NewDocumentCommand\tzLFnofyAtBegin{ m }
{
 \bool_gset_true:N \g_tzLFnofy_BEGIN_cmd_bool
 \tl_gset:No \g_tzLFnofy_BEGIN_cmd_tl { #1 }
}

%% \tzLFnofyAtEnd
\NewDocumentCommand\tzLFnofyAtEnd{ m }
{
 \bool_gset_true:N \g_tzLFnofy_END_cmd_bool
 \tl_gset:No \g_tzLFnofy_END_cmd_tl { #1 }
}

%%% \tzLFnofy (main)
%% \tzLFnofy : variable = \y
\NewDocumentCommand \tzLFnofy { t' o D<>{0,0} d"" }
{
 \tl_clear:N \l_tzLFnofy_opt_tl
 \tl_clear:N \l_tzLFnofy_path_tl
 \tl_clear:N \l_tzLFnofy_TEMP_cmd_tl
 \tl_clear:N \l_tzLFnofy_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzLFnofy_shift_tl
   { shift = { (#3) } }
 }
 { \tl_clear:N \l_tzLFnofy_shift_tl }

 \IfValueTF { #2 }
 { \tl_set:Nn \l_tzLFnofy_user_opt_tl { #2 } }
 { \tl_clear:N \l_tzLFnofy_user_opt_tl }

 \IfValueTF { #4 }
 { \tl_set:Nn \l_tzLFnofy_namepath_tl { name~path = #4 } }
 { \tl_clear:N \l_tzLFnofy_namepath_tl }

 \tzLFnofy_check_token:n
}

\cs_new:Npn \tzLFnofy_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzLFnofy_sub_fn ( }
}

\use:x{
 \NewDocumentCommand \exp_not:N \tzLFnofy_sub_fn
 { r() d() G{1}
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] + G{} O{} D<>{}
 }
}
{
 \tzLFnofy_domain_process #4

 \tl_put_right:Nx \l_tzLFnofy_opt_tl
   {
     [
%        samples = 201 ,
       \l_tzLFnofy_namepath_tl ,
       domain = \tzLFnofyFromVal \c_colon_str \tzLFnofyToVal , %%% [here?]
       variable = \exp_not:n { \y } ,
       \l_tzLFnofy_shift_tl ,
   }
 \tl_put_right:No \l_tzLFnofy_opt_tl
   {
       \l_tzLFnofy_user_opt_tl
     ]
   }

 % define LFofy: (X,Y)(XX,YY){slope num: dX/dY}
 \IfNoValueTF { #2 }
 {
   \tzgetxyval(#1){\tzLFnofyXvalS}{\tzLFnofyYvalS}
   \def\tzLFnofyDEF{#3*(\y-\tzLFnofyYvalS)+\tzLFnofyXvalS}
 }
 {
   \tzgetxyval(#1){\tzLFnofyXval}{\tzLFnofyYval}
   \tzgetxyval(#2){\tzLFnofyXXval}{\tzLFnofyYYval}
   \fp_compare:nT { \tzLFnofyYYval - \tzLFnofyYval = 0 }
     { \msg_error:nn { tzplot } { infinite~slope~error } }
   \edef\tzLFofySlope
     {
       (\tzLFnofyXXval-\tzLFnofyXval)/(\tzLFnofyYYval-\tzLFnofyYval)
     }
   \def\tzLFnofyDEF{\tzLFofySlope*(\y-\tzLFnofyYval)+\tzLFnofyXval}
 }

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_right:Nn \l_tzLFnofy_path_tl
     { plot ( \y , { \tzLFnofyDEF } ) }  % \y should not be expanded
 }
 {
   \tl_put_right:Nn \l_tzLFnofy_path_tl
     { plot ( { \tzLFnofyDEF } , \y ) }  % \y should not be expanded
 }
 % to resolve AtBegin issue with "plot" operation
 \bool_if:NTF \g_tzLFnofy_BEGIN_cmd_bool
   {
     \tl_put_right:No \l_tzLFnofy_TEMP_cmd_tl { \l_tzLFnofy_opt_tl }
     \tl_put_right:No \l_tzLFnofy_TEMP_cmd_tl { \l_tzLFnofy_path_tl }
     \exp_last_unbraced:Nf \path \l_tzLFnofy_TEMP_cmd_tl ;
     \path (current~subpath~start) coordinate (tzCSPS) ;
     \tl_put_right:No \l_tzLFnofy_cmd_tl { \l_tzLFnofy_opt_tl }
     \tl_put_right:No \l_tzLFnofy_cmd_tl { \g_tzLFnofy_BEGIN_cmd_tl } % insert
     \tl_put_right:Nn \l_tzLFnofy_cmd_tl { (tzCSPS) -- }          %
     \tl_put_right:No \l_tzLFnofy_cmd_tl { \l_tzLFnofy_path_tl }
   }
   {
     \tl_put_right:No \l_tzLFnofy_cmd_tl { \l_tzLFnofy_opt_tl }
     \tl_put_right:No \l_tzLFnofy_cmd_tl { \l_tzLFnofy_path_tl }
   }
 \bool_if:NT \g_tzLFnofy_END_cmd_bool
   {
     \tl_put_right:No \l_tzLFnofy_cmd_tl { \g_tzLFnofy_END_cmd_tl }   % append
   }
 \tl_put_right:Nn \l_tzLFnofy_cmd_tl
   { node [ #6 ] { #5 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzLFnofy_cmd_tl #7 ;

 \bool_gset_false:N \g_tzLFnofy_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzLFnofy_END_cmd_bool
}

\NewDocumentCommand\tzLFnofy_domain_process{ m m }
{
 \def\tzLFnofyFromVal{#1}
 \def\tzLFnofyToVal{#2}
}

%%% --- end of \tzLFnofy


%%% \tzfn
%%(variable=\x -- default)

\bool_new:N \g_tzfn_BEGIN_cmd_bool
\bool_new:N \g_tzfn_END_cmd_bool

%% \tzfnAtBegin
\NewDocumentCommand\tzfnAtBegin{ m }
{
 \bool_gset_true:N \g_tzfn_BEGIN_cmd_bool
 \tl_gset:No \g_tzfn_BEGIN_cmd_tl { #1 }
}

%% \tzfnAtEnd
\NewDocumentCommand\tzfnAtEnd{ m }
{
 \bool_gset_true:N \g_tzfn_END_cmd_bool
 \tl_gset:No \g_tzfn_END_cmd_tl { #1 }
}

%%% \tzfn (main)
%%(variable =\x)
\use:x{
 \NewDocumentCommand \exp_not:N \tzfn
 { t' O{} D<>{0,0} D""{} m
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzfn_opt_tl
 \tl_clear:N \l_tzfn_path_tl
 \tl_clear:N \l_tzfn_TEMP_cmd_tl
 \tl_clear:N \l_tzfn_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzfn_domain_process #6

 \tl_set:No \l_label_pos_tl { \tl_to_str:n { #5 } }
 \tl_set:No \l_tzfn_pathname_tl { \tl_tail:N \l_label_pos_tl }
 \tl_put_right:Nx \l_tzfn_opt_tl
   {
     [
       samples = 201 ,
       name~path =
         \tl_if_empty:nTF { #4 } { \l_tzfn_pathname_tl } { #4 } ,
       domain = \tzfnFromVal \c_colon_str \tzfnToVal ,
       shift = { (#3) } ,
%        variable = \exp_not:n { \x } ,
       \exp_not:n { #2 }
     ]
   }

 \bool_if:NTF { \l_tmpa_bool }
 {
   \tl_put_right:No \l_tzfn_path_tl
     { plot ( { #5 } , \exp_not:n { \x } ) }        % \x should not be expanded
 }
 {
   \tl_put_right:No \l_tzfn_path_tl
     { plot ( \exp_not:n { \x } , { #5 } ) }        % \x should not be expanded
 }
 % to resolve AtBegin issue with "plot" operation
 \bool_if:NTF \g_tzfn_BEGIN_cmd_bool
   {
     \tl_put_right:No \l_tzfn_TEMP_cmd_tl { \l_tzfn_opt_tl }
     \tl_put_right:No \l_tzfn_TEMP_cmd_tl { \l_tzfn_path_tl }
     \exp_last_unbraced:Nf \path \l_tzfn_TEMP_cmd_tl ;
     \path (current~subpath~start) coordinate (tzCSPS) ;
     \tl_put_right:No \l_tzfn_cmd_tl { \l_tzfn_opt_tl }
     \tl_put_right:No \l_tzfn_cmd_tl { \g_tzfn_BEGIN_cmd_tl } % insert
     \tl_put_right:Nn \l_tzfn_cmd_tl { (tzCSPS) -- }          %
     \tl_put_right:No \l_tzfn_cmd_tl { \l_tzfn_path_tl }
   }
   {
     \tl_put_right:No \l_tzfn_cmd_tl { \l_tzfn_opt_tl }
     \tl_put_right:No \l_tzfn_cmd_tl { \l_tzfn_path_tl }
   }
 \bool_if:NT \g_tzfn_END_cmd_bool
   {
     \tl_put_right:No \l_tzfn_cmd_tl { \g_tzfn_END_cmd_tl }   % append
   }
 \tl_put_right:Nn \l_tzfn_cmd_tl
   { node [ #8 ] { #7 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzfn_cmd_tl #9 ;

 \bool_gset_false:N \g_tzfn_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzfn_END_cmd_bool
}

\NewDocumentCommand\tzfn_domain_process{ m m }
{
 \def\tzfnFromVal{#1}
 \def\tzfnToVal{#2}
}

%%% --- end of \tzfn


%%% \tzfnofy
%% (variable = \y)

\bool_new:N \g_tzfnofy_BEGIN_cmd_bool
\bool_new:N \g_tzfnofy_END_cmd_bool

%% \tzfnofyAtBegin
\NewDocumentCommand\tzfnofyAtBegin{ m }
{
 \bool_gset_true:N \g_tzfnofy_BEGIN_cmd_bool
 \tl_gset:No \g_tzfnofy_BEGIN_cmd_tl { #1 }
}

%% \tzfnofyAtEnd
\NewDocumentCommand\tzfnofyAtEnd{ m }
{
 \bool_gset_true:N \g_tzfnofy_END_cmd_bool
 \tl_gset:No \g_tzfnofy_END_cmd_tl { #1 }
}

%%% \tzfnofy (main)
%% (variable=\y)
\use:x{
 \NewDocumentCommand \exp_not:N \tzfnofy
 { t' O{} D<>{0,0} D""{} m
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzfnofy_opt_tl
 \tl_clear:N \l_tzfnofy_path_tl
 \tl_clear:N \l_tzfnofy_TEMP_cmd_tl
 \tl_clear:N \l_tzfnofy_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzfnofy_domain_process #6

 \tl_set:No \l_label_pos_tl { \tl_to_str:n { #5 } }
 \tl_set:No \l_tzfnofy_pathname_tl { \tl_tail:N \l_label_pos_tl }
 \tl_put_right:Nx \l_tzfnofy_opt_tl
   {
     [
       samples = 201 ,
       name~path =
         \tl_if_empty:nTF { #4 } { \l_tzfnofy_pathname_tl } { #4 } ,
       domain = \tzfnofyFromVal \c_colon_str \tzfnofyToVal ,
       shift = { (#3) } ,
       variable = \exp_not:n { \y } ,
       \exp_not:n { #2 }
     ]
   }

 \bool_if:NTF \l_tmpa_bool
 {
   \tl_put_right:Nn \l_tzfnofy_path_tl
     { plot ( \y , { #5 } ) }        % \y should not be expanded
 }
 {
   \tl_put_right:Nn \l_tzfnofy_path_tl
     { plot ( { #5 } , \y ) }        % \y should not be expanded
 }
 % to resolve AtBegin issue with "plot" operation
 \bool_if:NTF \g_tzfnofy_BEGIN_cmd_bool
   {
     \tl_put_right:No \l_tzfnofy_TEMP_cmd_tl { \l_tzfnofy_opt_tl }
     \tl_put_right:No \l_tzfnofy_TEMP_cmd_tl { \l_tzfnofy_path_tl }
     \exp_last_unbraced:Nf \path \l_tzfnofy_TEMP_cmd_tl ;
     \path (current~subpath~start) coordinate (tzCSPS) ;
     \tl_put_right:No \l_tzfnofy_cmd_tl { \l_tzfnofy_opt_tl }
     \tl_put_right:No \l_tzfnofy_cmd_tl { \g_tzfnofy_BEGIN_cmd_tl } % insert
     \tl_put_right:Nn \l_tzfnofy_cmd_tl { (tzCSPS) -- }             %
     \tl_put_right:No \l_tzfnofy_cmd_tl { \l_tzfnofy_path_tl }
   }
   {
     \tl_put_right:No \l_tzfnofy_cmd_tl { \l_tzfnofy_opt_tl }
     \tl_put_right:No \l_tzfnofy_cmd_tl { \l_tzfnofy_path_tl }
   }
 \bool_if:NT \g_tzfnofy_END_cmd_bool
   {
     \tl_put_right:No \l_tzfnofy_cmd_tl { \g_tzfnofy_END_cmd_tl }   % append
   }
 \tl_put_right:Nn \l_tzfnofy_cmd_tl
   { node [ #8 ] { #7 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzfnofy_cmd_tl #9 ;

 \bool_gset_false:N \g_tzfnofy_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzfnofy_END_cmd_bool
}

\NewDocumentCommand\tzfnofy_domain_process{ m m }
{
 \def\tzfnofyFromVal{#1}
 \def\tzfnofyToVal{#2}
}

%%% --- end of \tzfnofy


%%% \tzfnmax
%% (variable=\x -- default)

\bool_new:N \g_tzfnmax_BEGIN_cmd_bool
\bool_new:N \g_tzfnmax_END_cmd_bool

%% \tzfnmaxAtBegin
\NewDocumentCommand\tzfnmaxAtBegin{ m }
{
 \bool_gset_true:N \g_tzfnmax_BEGIN_cmd_bool
 \tl_gset:No \g_tzfnmax_BEGIN_cmd_tl { #1 }
}

%% \tzfnmaxAtEnd
\NewDocumentCommand\tzfnmaxAtEnd{ m }
{
 \bool_gset_true:N \g_tzfnmax_END_cmd_bool
 \tl_gset:No \g_tzfnmax_END_cmd_tl { #1 }
}


%%% \tzfnmax (main)
%% (variable=\x)
\use:x{
 \NewDocumentCommand \exp_not:N \tzfnmax
 { t' O{} D<>{0,0} D""{} m
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzfnmax_opt_tl
 \tl_clear:N \l_tzfnmax_path_tl
 \tl_clear:N \l_tzfnmax_TEMP_cmd_tl
 \tl_clear:N \l_tzfnmax_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzfnmax_domain_process #6

 \tl_put_right:Nx \l_tzfnmax_opt_tl
   {
     [
       thick , samples = 201 ,
       name~path = #4 ,
       domain = \tzfnmaxFromVal \c_colon_str \tzfnmaxToVal ,
       shift = { (#3) } ,
%        varialbe = \exp_not:n { \x } ,
       \exp_not:n { #2 }
     ]
   }

 \bool_if:NTF { \l_tmpa_bool }
 {
   \tl_put_right:Nn \l_tzfnmax_path_tl
     { plot ( { max(#5) } , \x ) }        % \x should not be expanded
 }
 {
   \tl_put_right:Nn \l_tzfnmax_path_tl
     { plot ( \x , { max(#5) } ) }        % \x should not be expanded
 }
 % to resolve AtBegin issue with "plot" operation
 \bool_if:NTF \g_tzfnmax_BEGIN_cmd_bool
   {
     \tl_put_right:No \l_tzfnmax_TEMP_cmd_tl { \l_tzfnmax_opt_tl }
     \tl_put_right:No \l_tzfnmax_TEMP_cmd_tl { \l_tzfnmax_path_tl }
     \exp_last_unbraced:Nf \path \l_tzfnmax_TEMP_cmd_tl ;
     \path (current~subpath~start) coordinate (tzCSPS) ;
     \tl_put_right:No \l_tzfnmax_cmd_tl { \l_tzfnmax_opt_tl }
     \tl_put_right:No \l_tzfnmax_cmd_tl { \g_tzfnmax_BEGIN_cmd_tl } % insert
     \tl_put_right:Nn \l_tzfnmax_cmd_tl { (tzCSPS) -- }          %
     \tl_put_right:No \l_tzfnmax_cmd_tl { \l_tzfnmax_path_tl }
   }
   {
     \tl_put_right:No \l_tzfnmax_cmd_tl { \l_tzfnmax_opt_tl }
     \tl_put_right:No \l_tzfnmax_cmd_tl { \l_tzfnmax_path_tl }
   }
 \bool_if:NT \g_tzfnmax_END_cmd_bool
   {
     \tl_put_right:No \l_tzfnmax_cmd_tl { \g_tzfnmax_END_cmd_tl }   % append
   }
 \tl_put_right:Nn \l_tzfnmax_cmd_tl
   { node [ #8 ] { #7 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzfnmax_cmd_tl #9 ;

 \bool_gset_false:N \g_tzfnmax_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzfnmax_END_cmd_bool
}

\NewDocumentCommand\tzfnmax_domain_process{ m m }
{
 \def\tzfnmaxFromVal{#1}
 \def\tzfnmaxToVal{#2}
}

%%% --- end of \tzfnmax



%%% \tzfnmin
%% (variable=\x -- default)

\bool_new:N \g_tzfnmin_BEGIN_cmd_bool
\bool_new:N \g_tzfnmin_END_cmd_bool

%% \tzfnminAtBegin
\NewDocumentCommand\tzfnminAtBegin{ m }
{
 \bool_gset_true:N \g_tzfnmin_BEGIN_cmd_bool
 \tl_gset:No \g_tzfnmin_BEGIN_cmd_tl { #1 }
}

%% \tzfnminAtEnd
\NewDocumentCommand\tzfnminAtEnd{ m }
{
 \bool_gset_true:N \g_tzfnmin_END_cmd_bool
 \tl_gset:No \g_tzfnmin_END_cmd_tl { #1 }
}



%%% \tzfnmin (main)
%% (variable=\x)
\use:x{
 \NewDocumentCommand \exp_not:N \tzfnmin
 { t' O{} D<>{0,0} D""{} m
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzfnmin_opt_tl
 \tl_clear:N \l_tzfnmin_path_tl
 \tl_clear:N \l_tzfnmin_TEMP_cmd_tl
 \tl_clear:N \l_tzfnmin_cmd_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzfnmin_domain_process #6

%  \tl_set:No \l_label_pos_tl { \tl_to_str:n { #5 } }
%  \tl_set:No \l_tzfnmin_pathname_tl { \tl_tail:N \l_label_pos_tl }
 \tl_put_right:Nx \l_tzfnmin_opt_tl
   {
     [
       thick , samples = 201 ,
       name~path = #4 ,
%          \tl_if_empty:nTF { #4 } { } { #4 } ,
       domain = \tzfnminFromVal \c_colon_str \tzfnminToVal ,
       shift = { (#3) } ,
%        variable = \exp_not:n { \x } ,
       \exp_not:n { #2 }
     ]
   }

 \bool_if:NTF { \l_tmpa_bool }
 {
   \tl_put_right:Nn \l_tzfnmin_path_tl
     { plot ( { min(#5) } , \x ) }        % \x should not be expanded
 }
 {
   \tl_put_right:Nn \l_tzfnmin_path_tl
     { plot ( \x , { min(#5) } ) }        % \x should not be expanded
 }
 % to resolve AtBegin issue with "plot" operation
 \bool_if:NTF \g_tzfnmin_BEGIN_cmd_bool
   {
     \tl_put_right:No \l_tzfnmin_TEMP_cmd_tl { \l_tzfnmin_opt_tl }
     \tl_put_right:No \l_tzfnmin_TEMP_cmd_tl { \l_tzfnmin_path_tl }
     \exp_last_unbraced:Nf \path \l_tzfnmin_TEMP_cmd_tl ;
     \path (current~subpath~start) coordinate (tzCSPS) ;
     \tl_put_right:No \l_tzfnmin_cmd_tl { \l_tzfnmin_opt_tl }
     \tl_put_right:No \l_tzfnmin_cmd_tl { \g_tzfnmin_BEGIN_cmd_tl } % insert
     \tl_put_right:Nn \l_tzfnmin_cmd_tl { (tzCSPS) -- }             %
     \tl_put_right:No \l_tzfnmin_cmd_tl { \l_tzfnmin_path_tl }
   }
   {
     \tl_put_right:No \l_tzfnmin_cmd_tl { \l_tzfnmin_opt_tl }
     \tl_put_right:No \l_tzfnmin_cmd_tl { \l_tzfnmin_path_tl }
   }
 \bool_if:NT \g_tzfnmin_END_cmd_bool
   {
     \tl_put_right:No \l_tzfnmin_cmd_tl { \g_tzfnmin_END_cmd_tl }   % append
   }
 \tl_put_right:Nn \l_tzfnmin_cmd_tl
   { node [ #8 ] { #7 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzfnmin_cmd_tl #9 ;

 \bool_gset_false:N \g_tzfnmin_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzfnmin_END_cmd_bool
}

\NewDocumentCommand\tzfnmin_domain_process{ m m }
{
 \def\tzfnminFromVal{#1}
 \def\tzfnminToVal{#2}
}

%%% --- end of \tzfnmin


%%% pdf

%% normal distribution

\NewExpandableDocumentCommand\tzpdfN{ s m m }
{
 \IfBooleanTF { #1 }
 { % standard deviation
   1/(#3*sqrt(2*pi))*exp( -1/2*( (\exp_not:n{\x}-#2)^2 / (#3)^2 ) )
 }
 { % variance (default)
   1/(sqrt(#3)*sqrt(2*pi))*exp(-1/2*((\exp_not:n{\x}-#2)^2/(sqrt(#3))^2))
 }
}


%% standard normal distribution

\NewExpandableDocumentCommand\tzpdfZ{ }
{
%  \IfBooleanTF { #1 } {}{}  % NOT USED! (to avoid coding error)
 1/sqrt(2*pi)*exp( -1/2*( \exp_not:n{\x} )^2 )
}



%%% \tzfnarea
%% no shift, no name path

\use:x{
 \NewDocumentCommand \exp_not:N \tzfnarea
 { s O{} m >{ \SplitArgument {1} { \tl_to_str:n {:} } } r[] G{.3} D<>{} }
}
{
 \tl_clear:N \l_tzfnarea_cmd_tl

 \tl_if_empty:nTF { #5 }
 { \renewcommand\tzfillopacity{\tz@initial@fill@opacity} }
 { \renewcommand\tzfillopacity{#5} }

 \tzfnarea_domain_process #4

 % collect fill options
 \IfBooleanTF { #1 }
 {
   \tl_put_right:Nx \l_tzfnarea_cmd_tl
     {
       [ fill=\tzfillcolor , fill~opacity = \tzfillopacity ,
         text~opacity = 1 , \exp_not:n { #2 } ]
     }
 }
 {
   \tl_put_right:Nn \l_tzfnarea_cmd_tl
     { [ #2 ] }
 }


   \tl_put_right:Nx \l_tzfnarea_cmd_tl
     {
       (\tzfnareaFromVal,0) -- plot
          [ samples = 201 ,
            domain = \tzfnareaFromVal \c_colon_str \tzfnareaToVal ,
%             variable = \exp_not:n { \x } ,
          ]
     }
   \tl_put_right:No \l_tzfnarea_cmd_tl
     {
          ( \exp_not:n { \x } , { #3 } ) -- (\tzfnareaToVal,0)
     }

 % final action
 \begin{pgfonlayer}{ \tzfnarealayer } % default = behind
 \exp_last_unbraced:Nf
   \path \l_tzfnarea_cmd_tl #6 ;
 \end{pgfonlayer}
}

\NewDocumentCommand\tzfnarea_domain_process{ m m }
{
 \def\tzfnareaFromVal{#1}
 \def\tzfnareaToVal{#2}
}

%%% --- end of \tzfnarea


\NewDocumentCommand\tzfnarealine{ t' O{} m m O{} D(){0,0} g O{} D(){0,0} }
{
 \tzvXpointat{#3}{#4}(tzfnAL)

 \IfBooleanTF { #1 }
 {
   \begin{pgfonlayer}{\tzfnarealayer}
   \tzto [ \tzfnALstyle , #2 , #8 ] (tzfnAL) (tzfnAL -| #6)
   \end{pgfonlayer}
 }
 {
   \begin{pgfonlayer}{\tzfnarealayer}
   \tzto [ \tzfnALstyle , #2 , #8 ] (tzfnAL) (tzfnAL |- #6)
   \end{pgfonlayer}
 }

 \IfValueT { #7 }
 {
   \tzvXpointat{#3}{#7}(tzfnAR)

   \IfBooleanTF { #1 }
   {
     \begin{pgfonlayer}{\tzfnarealayer}
     \tzto [ \tzfnALstyle , #2 , #8 ] (tzfnAR) (tzfnAR -| #9)
     \end{pgfonlayer}
   }
   {
     \begin{pgfonlayer}{\tzfnarealayer}
     \tzto [ \tzfnALstyle , #2 , #8 ] (tzfnAR) (tzfnAR|-#9)
     \end{pgfonlayer}
   }
 }
}




%%% \tzvfnat
%% -- vertical line at x

\bool_new:N \g_tzvfnat_BEGIN_cmd_bool
\bool_new:N \g_tzvfnat_END_cmd_bool

%% \tzvfnatAtBegin
\NewDocumentCommand\tzvfnatAtBegin{ m }
{
 \bool_gset_true:N \g_tzvfnat_BEGIN_cmd_bool
 \tl_gset:No \g_tzvfnat_BEGIN_cmd_tl { #1 }
}

%% \tzvfnatAtEnd
\NewDocumentCommand\tzvfnatAtEnd{ m }
{
 \bool_gset_true:N \g_tzvfnat_END_cmd_bool
 \tl_gset:No \g_tzvfnat_END_cmd_tl { #1 }
}

%% \tzvfnat (main)
\use:x{
 \NewDocumentCommand \exp_not:N \tzvfnat
 { O{} D<>{0,0} D""{} m
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } d[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzvfnat_cmd_tl

 \IfValueT { #5 }  { \tzvfnat_domain_process #5 }

 \tl_put_right:Nx \l_tzvfnat_cmd_tl
   {
     [
%        samples = 201 ,
       name~path = #3 ,
       shift = { (#2) } ,
       \exp_not:n { #1 }
     ]
   }
 \bool_if:NT \g_tzvfnat_BEGIN_cmd_bool
   { \tl_put_right:No \l_tzvfnat_cmd_tl { \g_tzvfnat_BEGIN_cmd_tl } }
 \IfValueTF { #5 }
 {
   \tl_put_right:Nn \l_tzvfnat_cmd_tl
     { (#4,\tzvfnatFromVal) -- (#4,\tzvfnatToVal) }
 }
 {
   \tl_put_right:Nn \l_tzvfnat_cmd_tl
     {
          (#4,0 |- current~bounding~box.south)
       -- (#4,0 |- current~bounding~box.north)
     }
 }
 \bool_if:NT \g_tzvfnat_END_cmd_bool
   { \tl_put_right:No \l_tzvfnat_cmd_tl { \g_tzvfnat_END_cmd_tl } }
 \tl_put_right:Nn \l_tzvfnat_cmd_tl
   { node [ #7 ] { #6 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzvfnat_cmd_tl #8 ;

 \bool_gset_false:N \g_tzvfnat_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzvfnat_END_cmd_bool
}

\NewDocumentCommand\tzvfnat_domain_process{ m m }
{
 \def\tzvfnatFromVal{#1}
 \def\tzvfnatToVal{#2}
}

%%% --- end of \tzvfnat


%%% \tzvfn (On)
%% -- vertical line through (x,y)

\bool_new:N \g_tzvfn_BEGIN_cmd_bool
\bool_new:N \g_tzvfn_END_cmd_bool

%% \tzvfnAtBegin
\NewDocumentCommand\tzvfnAtBegin{ m }
{
 \bool_gset_true:N \g_tzvfn_BEGIN_cmd_bool
 \tl_gset:No \g_tzvfn_BEGIN_cmd_tl { #1 }
}

%% \tzvfnAtEnd
\NewDocumentCommand\tzvfnAtEnd{ m }
{
 \bool_gset_true:N \g_tzvfn_END_cmd_bool
 \tl_gset:No \g_tzvfn_END_cmd_tl { #1 }
}

%%% \tzvfn (main)
\use:x{
 \NewDocumentCommand \exp_not:N \tzvfn
 { O{} d<> D""{} r()
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } d[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzvfn_cmd_tl

 \IfValueT { #5 }  { \tzvfn_domain_process #5 }

 \tl_put_right:Nx \l_tzvfn_cmd_tl
   {
     [
       name~path = #3 ,
       \exp_not:n { #1 }
     ]
   }
 \bool_if:NT \g_tzvfn_BEGIN_cmd_bool
   { \tl_put_right:No \l_tzvfn_cmd_tl { \g_tzvfn_BEGIN_cmd_tl } }
 \IfValueTF { #5 }
 {
   \IfValueTF { #2 }
   {
     \tl_put_right:Nn \l_tzvfn_cmd_tl
     {
       ([shift = { (#2) }]#4 |- 0,\tzvfnFromVal) --
       ([shift = { (#2) }]#4 |- 0,\tzvfnToVal) }
   }
   {
     \tl_put_right:Nn \l_tzvfn_cmd_tl
     { (#4 |- 0,\tzvfnFromVal) -- (#4 |- 0,\tzvfnToVal) }
   }
 }
 {
   \IfValueTF { #2 }
   {
     \tl_put_right:Nn \l_tzvfn_cmd_tl
     {
       ([shift = { (#2) }]#4 |- current~bounding~box.south) --
       ([shift = { (#2) }]#4 |- current~bounding~box.north)
     }
   }
   {
     \tl_put_right:Nn \l_tzvfn_cmd_tl
     {
       (#4 |- current~bounding~box.south) --
       (#4 |- current~bounding~box.north)
     }
   }
 }
 \bool_if:NT \g_tzvfn_END_cmd_bool
   { \tl_put_right:No \l_tzvfn_cmd_tl { \g_tzvfn_END_cmd_tl } }
 \tl_put_right:Nn \l_tzvfn_cmd_tl
   { node [ #7 ] { #6 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzvfn_cmd_tl #8 ;

 \bool_gset_false:N \g_tzvfn_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzvfn_END_cmd_bool
}

\NewDocumentCommand\tzvfn_domain_process{ m m }
{
 \def\tzvfnFromVal{#1}
 \def\tzvfnToVal{#2}
}

%%% --- end of \tzvfn


%%% \tzhfnat
%% -- horizontal line at y

\bool_new:N \g_tzhfnat_BEGIN_cmd_bool
\bool_new:N \g_tzhfnat_END_cmd_bool

%% \tzhfnatAtBegin
\NewDocumentCommand\tzhfnatAtBegin{ m }
{
 \bool_gset_true:N \g_tzhfnat_BEGIN_cmd_bool
 \tl_gset:No \g_tzhfnat_BEGIN_cmd_tl { #1 }
}

%% \tzhfnatAtEnd
\NewDocumentCommand\tzhfnatAtEnd{ m }
{
 \bool_gset_true:N \g_tzhfnat_END_cmd_bool
 \tl_gset:No \g_tzhfnat_END_cmd_tl { #1 }
}

%% \tzhfnat (main)
\use:x{
 \NewDocumentCommand \exp_not:N \tzhfnat
 { O{} D<>{0,0} D""{} m
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } d[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzhfnat_cmd_tl

 \IfValueT { #5 }  { \tzhfnat_domain_process #5 }

 \tl_put_right:Nx \l_tzhfnat_cmd_tl
   {
     [
       name~path = #3 ,
       shift = { (#2) } ,
       variable = \exp_not:n { \x } ,
       \exp_not:n { #1 }
     ]
   }
 \bool_if:NT \g_tzhfnat_BEGIN_cmd_bool
   { \tl_put_right:No \l_tzhfnat_cmd_tl { \g_tzhfnat_BEGIN_cmd_tl } }
 \IfValueTF { #5 }
 {
   \tl_put_right:Nn \l_tzhfnat_cmd_tl
     { (\tzhfnatFromVal,#4) -- (\tzhfnatToVal,#4) }
 }
 {
   \tl_put_right:Nn \l_tzhfnat_cmd_tl
     {
          (0,#4 -| current~bounding~box.west)
       -- (0,#4 -| current~bounding~box.east)
     }
 }
 \bool_if:NT \g_tzhfnat_END_cmd_bool
   { \tl_put_right:No \l_tzhfnat_cmd_tl { \g_tzhfnat_END_cmd_tl } }
 \tl_put_right:Nn \l_tzhfnat_cmd_tl
   { node [ #7 ] { #6 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzhfnat_cmd_tl #8 ;

 \bool_gset_false:N \g_tzhfnat_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzhfnat_END_cmd_bool
}

\NewDocumentCommand\tzhfnat_domain_process{ m m }
{
 \def\tzhfnatFromVal{#1}
 \def\tzhfnatToVal{#2}
}

%%% --- end of \tzhfnat


%%% \tzhfn (On)
%% -- horizontal line through (x,y)

\bool_new:N \g_tzhfn_BEGIN_cmd_bool
\bool_new:N \g_tzhfn_END_cmd_bool

%% \tzhfnAtBegin
\NewDocumentCommand\tzhfnAtBegin{ m }
{
 \bool_gset_true:N \g_tzhfn_BEGIN_cmd_bool
 \tl_gset:No \g_tzhfn_BEGIN_cmd_tl { #1 }
}

%% \tzhfnAtEnd
\NewDocumentCommand\tzhfnAtEnd{ m }
{
 \bool_gset_true:N \g_tzhfn_END_cmd_bool
 \tl_gset:No \g_tzhfn_END_cmd_tl { #1 }
}

%% \tzhfn (main)
\use:x{
 \NewDocumentCommand \exp_not:N \tzhfn
 { O{} d<> D""{} r()
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } d[] +G{} O{} D<>{}
 }
}
{
 \tl_clear:N \l_tzhfn_cmd_tl

 \IfValueT { #5 }  { \tzhfn_domain_process #5 }

 \tl_put_right:Nx \l_tzhfn_cmd_tl
   {
     [
       name~path = #3 ,
       variable = \exp_not:n { \x } ,
       \exp_not:n { #1 }
     ]
   }
 \bool_if:NT \g_tzhfn_BEGIN_cmd_bool
   { \tl_put_right:No \l_tzhfn_cmd_tl { \g_tzhfn_BEGIN_cmd_tl } }
 \IfValueTF { #5 }
 {
   \IfValueTF { #2 }
   {
     \tl_put_right:Nn \l_tzhfn_cmd_tl
     {
       ([shift = { (#2) }]\tzhfnFromVal,0 |- #4) --
       ([shift = { (#2) }]\tzhfnToVal,0 |- #4)
     }
   }
   {
     \tl_put_right:Nn \l_tzhfn_cmd_tl
     {
       (\tzhfnFromVal,0 |- #4) --
       (\tzhfnToVal,0 |- #4)
     }
   }
 }
 {
   \IfValueTF { #2 }
   {
     \tl_put_right:Nn \l_tzhfn_cmd_tl
     {
          ([shift = { (#2) }]#4 -| current~bounding~box.west)
       -- ([shift = { (#2) }]#4 -| current~bounding~box.east)
     }
   }
   {
     \tl_put_right:Nn \l_tzhfn_cmd_tl
     {
          (#4 -| current~bounding~box.west)
       -- (#4 -| current~bounding~box.east)
     }
   }
 }
 \bool_if:NT \g_tzhfn_END_cmd_bool
   { \tl_put_right:No \l_tzhfn_cmd_tl { \g_tzhfn_END_cmd_tl } }
 \tl_put_right:Nn \l_tzhfn_cmd_tl
   { node [ #7 ] { #6 } }
 % final action
 \exp_last_unbraced:Nf \draw \l_tzhfn_cmd_tl #8 ;

 \bool_gset_false:N \g_tzhfn_BEGIN_cmd_bool
 \bool_gset_false:N \g_tzhfn_END_cmd_bool
}

\NewDocumentCommand\tzhfn_domain_process{ m m }
{
 \def\tzhfnFromVal{#1}
 \def\tzhfnToVal{#2}
}

%%% --- end of \tzhfn


%%%%% Intersections

%%% \tzXpoint -- intersection point of two paths
\NewDocumentCommand\tzXpoint
 { s O{} m m D(){intersection} O{1} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzXpoint_cmd_tl
%%%%%% to use string replacement for label positions
 \IfValueTF { #8 }
 {
       \tl_if_in:nnTF { #8 } { [ }
   { \extract_posopt:w #8 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #8 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #8 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%
 \path [ name~intersections = { of = #3 ~ and ~ #4 , name = #5 } ] ;
 \tl_put_right:Nn \l_tzXpoint_cmd_tl
 {
   (#5-#6) coordinate (#5)
   \IfBooleanTF {#1}
   { node [ tzdot , fill ,        minimum~size = #9  , }
   { node [ tzdot , draw = none , minimum~size = 0pt , }
 }

 \tl_put_right:Nx \l_tzXpoint_cmd_tl
 {
       label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #7 } } , % pos_str
 }

 \tl_put_right:Nn \l_tzXpoint_cmd_tl
 {
            #2
          ] {}
 }

 \exp_last_unbraced:Nf \path \l_tzXpoint_cmd_tl ;
}

%%% --- end of \tzXpoint


%%% \tzLFnXpoint : linear Xpoint
\NewDocumentCommand\tzLFnXpoint
 { s O{} m m o D(){} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzLFnXpoint_cmd_tl

%%%%%% to use string replacement for label positions
 \IfValueTF { #8 }
 {
       \tl_if_in:nnTF { #8 } { [ }
   { \extract_posopt:w #8 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #8 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #8 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \IfValueTF { #5 }
 {
   \def\x{#5}
   \path (\x,{#3}) coordinate (tzLFnXA-1) (\x,{#4}) coordinate (tzLFnXB-1);
   \def\x{\fp_eval:n {1.01*#5+.1}}
   \path (\x,{#3}) coordinate (tzLFnXA-2) (\x,{#4}) coordinate (tzLFnXB-2);
 }
 {
   \def\x{0}
   \path (\x,{#3}) coordinate (tzLFnXA-1) (\x,{#4}) coordinate (tzLFnXB-1);
   \def\x{.1}
   \path (\x,{#3}) coordinate (tzLFnXA-2) (\x,{#4}) coordinate (tzLFnXB-2);
 }

 \tl_put_right:Nn \l_tzLFnXpoint_cmd_tl
 {
   (intersection~of~tzLFnXA-1--tzLFnXA-2 ~and~ tzLFnXB-1--tzLFnXB-2)
   coordinate (#6)
   \IfBooleanTF {#1}
   { node [ tzdot , fill ,        minimum~size = #9  , }
   { node [ tzdot , draw = none , minimum~size = 0pt , }
 }

 \tl_put_right:Nx \l_tzLFnXpoint_cmd_tl
 {
       label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #7 } } , % pos_str
 }

 \tl_put_right:Nn \l_tzLFnXpoint_cmd_tl
 {
            #2
          ] {}
 }

 \exp_last_unbraced:Nf \draw \l_tzLFnXpoint_cmd_tl ;
}

%%% --- end of \tzLFnXpoint


%%% \tzvXpointat  -- vertical intersection point at x
%%% *[<opt>]{<path>}(<coor>)(<coor name>)[<nth>]{<label>}[<[<opt>]angle>](<dotsize>)
\NewDocumentCommand\tzvXpointat
 { s O{} m m D(){intersection} O{1} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzvXpointat_cmd_tl

 \tzvfnat[draw=none]"tzvXpoint-At" {#4} % depends on (current bounding box)

%%%%%% to use string replacement for label positions
 \IfValueTF { #8 }
 {
       \tl_if_in:nnTF { #8 } { [ }
   { \extract_posopt:w #8 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #8 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #8 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \path [ name~intersections = { of = tzvXpoint-At ~and~ #3 , name = #5 } ] ;

 \tl_put_right:Nn \l_tzvXpointat_cmd_tl
 {
   (#5-#6) coordinate (#5)
   \IfBooleanTF {#1}
   { node [ tzdot , fill ,        minimum~size = #9  , }
   { node [ tzdot , draw = none , minimum~size = 0pt , }
 }

 \tl_put_right:Nx \l_tzvXpointat_cmd_tl
 {
      label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #7 } } , % pos_str
 }

 \tl_put_right:Nn \l_tzvXpointat_cmd_tl
 {
            #2
          ] {}
 }

 \exp_last_unbraced:Nf \path \l_tzvXpointat_cmd_tl ;
 \tl_clear:N \tzvXpointat_cmd_tl
}

%%% --- end of \tzvXpointat


%%% \tzvXpoint (On)
%%% -- vertical intersection point at (x,y) of a path
%%% *[<opt>]{<path>}(<coor>)(<coor name>)[<nth>]{<label>}[<[<opt>]angle>](<dotsize>)
\NewDocumentCommand\tzvXpoint
 { s O{} m r() D(){intersection} O{1} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzvXpoint_cmd_tl

 \tzvfn[draw=none]"tzvXpoint-On"(#4) % depends on (current bounding box)

%%%%%% to use string replacement for label positions
 \IfValueTF { #8 }
 {
       \tl_if_in:nnTF { #8 } { [ }
   { \extract_posopt:w #8 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #8 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #8 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \path [ name~intersections = { of = tzvXpoint-On ~and~ #3 , name = #5 } ] ;
 \tl_put_right:Nn \l_tzvXpoint_cmd_tl
 {
   (#5-#6) coordinate (#5)
   \IfBooleanTF {#1}
   { node [ tzdot , fill ,        minimum~size = #9  , }
   { node [ tzdot , draw = none , minimum~size = 0pt , }
 }

 \tl_put_right:Nx \l_tzvXpoint_cmd_tl
 {
      label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #7 } } , % pos_str
 }

 \tl_put_right:Nn \l_tzvXpoint_cmd_tl
 {
            #2
          ] {}
 }

 \exp_last_unbraced:Nf \path \l_tzvXpoint_cmd_tl ;
 \tl_clear:N \l_tzvXpoint_cmd_tl
}

%%% --- end of \tzvXpoint



%%% \tzhXpointat  -- horizontal intersection point at y
\NewDocumentCommand\tzhXpointat
 { s O{} m m D(){intersection} O{1} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzhXpointat_cmd_tl

 \tzhfnat[draw=none]"tzhXpoint-At"{#4} % depends on (current bounding box)

%%%%%% to use string replacement for label positions
 \IfValueTF { #8 }
 {
       \tl_if_in:nnTF { #8 } { [ }
   { \extract_posopt:w #8 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #8 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #8 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \path [ name~intersections = { of = tzhXpoint-At ~and~ #3 , name = #5 } ] ;
 \tl_put_right:Nn \l_tzhXpointat_cmd_tl
 {
   (#5-#6) coordinate (#5)
   \IfBooleanTF {#1}
   { node [ tzdot , fill ,        minimum~size = #9  , }
   { node [ tzdot , draw = none , minimum~size = 0pt , }
 }

 \tl_put_right:Nx \l_tzhXpointat_cmd_tl
 {
      label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #7 } } , % pos_str
 }

 \tl_put_right:Nn \l_tzhXpointat_cmd_tl
 {
            #2
          ] {}
 }

 \exp_last_unbraced:Nf \path \l_tzhXpointat_cmd_tl ;
 \tl_clear:N \l_tzhXpointat_cmd_tl
}

%%% --- end of \tzhXpointat


%%% \tzhXpoint (On)  -- horizontal intersection point at (x,y)
\NewDocumentCommand\tzhXpoint
 { s O{} m r() D(){intersection} O{1} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tzhXpoint_cmd_tl

 \tzhfn[draw=none]"tzhXpoint-On"(#4) % depends on (current bounding box)

%%%%%% to use string replacement for label positions
 \IfValueTF { #8 }
 {
       \tl_if_in:nnTF { #8 } { [ }
   { \extract_posopt:w #8 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #8 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #8 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \path [ name~intersections = { of = tzhXpoint-On ~and~ #3 , name = #5 } ] ;

 \tl_put_right:Nn \l_tzhXpoint_cmd_tl
 {
   (#5-#6) coordinate (#5)
   \IfBooleanTF {#1}
   { node [ tzdot , fill ,        minimum~size = #9  , }
   { node [ tzdot , draw = none , minimum~size = 0pt , }
 }

 \tl_put_right:Nx \l_tzhXpoint_cmd_tl
 {
      label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #7 } } , % pos_str
 }

 \tl_put_right:Nn \l_tzhXpoint_cmd_tl
 {
            #2
          ] {}
 }

 \exp_last_unbraced:Nf \path \l_tzhXpoint_cmd_tl ;
 \tl_clear:N \l_tzhXpoint_cmd_tl
}

%%% --- end of \tzhXpoint



%%%%% Axes

%%% \tzaxes

\NewDocumentCommand\tzaxes{ s O{} D<>{0,0} D""{axes} }
{
 \tl_clear:N \l_tzaxes_opt_tl
 \tl_clear:N \l_tzaxes_x_cmd_tl
 \tl_clear:N \l_tzaxes_y_cmd_tl
 \tl_clear:N \l_tzaxes_path_cmd_tl
 \tl_clear:N \l_tzaxes_name_path_tl
 \tl_clear:N \l_tzaxes_shift_coor_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tl_set:Nn \l_tzaxes_opt_tl { [ -> , #2 ] }

 \tl_set:Nn \l_tzaxes_name_path_tl { #4 }
 \tl_set:Nn \l_tzaxes_shift_coor_tl { #3 }

 \tzaxes_check_token:n
}

\cs_new:Npn \tzaxes_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
 { \tzaxes_final_actions ( }
}

\NewDocumentCommand\tzaxes_final_actions{ r() d() +G{} O{} +G{} O{} }
{
 \IfNoValueTF { #2 }
 {
   \tl_set:Nx \l_tzaxes_x_cmd_tl
   {
     ( 0,0 |- {\l_tzaxes_shift_coor_tl} ) -- ( #1 |- {\l_tzaxes_shift_coor_tl} )
       node [ right , \exp_not:n { #4 } ] { \exp_not:n { #3 } }
   }
   \tl_set:Nx \l_tzaxes_y_cmd_tl
   {
     ( {\l_tzaxes_shift_coor_tl} |- 0,0 ) -- ( {\l_tzaxes_shift_coor_tl} |- #1 )
       node [ above , \exp_not:n { #6 } ] { \exp_not:n { #5 } }
   }
   \tl_set:Nx \l_tzaxes_path_cmd_tl
   {
     ( 0,0 |- {\l_tzaxes_shift_coor_tl} ) -- ( #1 |- {\l_tzaxes_shift_coor_tl} )
     ( {\l_tzaxes_shift_coor_tl} |- 0,0 )
     -- ( {\l_tzaxes_shift_coor_tl} |- \exp_not:n { #1 } )
   }
 }
 {
   \tl_set:Nx \l_tzaxes_x_cmd_tl
   {
     ( #1 |- {\l_tzaxes_shift_coor_tl} )  -- ( #2 |- {\l_tzaxes_shift_coor_tl} )
       node [ right , \exp_not:n { #4 } ] { \exp_not:n { #3 } }
   }
   \tl_set:Nx \l_tzaxes_y_cmd_tl
   {
     ( {\l_tzaxes_shift_coor_tl} |- #1 )  -- ( {\l_tzaxes_shift_coor_tl} |- #2 )
       node [ above , \exp_not:n { #6 } ] { \exp_not:n { #5 } }
   }
   \tl_set:Nx \l_tzaxes_path_cmd_tl
   {
     ( #1 |- {\l_tzaxes_shift_coor_tl} )  -- ( #2 |- {\l_tzaxes_shift_coor_tl} )
     ( {\l_tzaxes_shift_coor_tl} |- #1 )  -- ( {\l_tzaxes_shift_coor_tl} |- #2 )
   }
 }

 \tl_put_left:No \l_tzaxes_x_cmd_tl { \l_tzaxes_opt_tl }
 \tl_put_left:No \l_tzaxes_y_cmd_tl { \l_tzaxes_opt_tl }
 \tl_put_left:No \l_tzaxes_path_cmd_tl
   { [ name~path = \l_tzaxes_name_path_tl ] }

 % final actions
 \exp_last_unbraced:Nf \draw \l_tzaxes_x_cmd_tl ;
 \exp_last_unbraced:Nf \draw \l_tzaxes_y_cmd_tl ;
 \exp_last_unbraced:Nf \path \l_tzaxes_path_cmd_tl ;

  \bool_if:NT \l_tmpa_bool
 {
   \coordinate (bbxOpposite) at (current~bounding~box.north~east) ;
   \coordinate (bbxOrigin) at (current~bounding~box.south~west) ;
   \useasboundingbox (bbxOrigin) rectangle (bbxOpposite) ;
 }
}

%%% -- end of \tzaxes


%%% \tzaxesL  -- simpler version of \tzaxes

\bool_new:N \l_tzaxesL_shift_coor_bool

\NewDocumentCommand\tzaxesL{ t' O{} d<> D""{axesL}}
{
 \tl_clear:N \l_tzaxesL_opt_tl
 \tl_clear:N \l_tzaxesL_x_cmd_tl
 \tl_clear:N \l_tzaxesL_y_cmd_tl
 \tl_clear:N \l_tzaxesL_path_cmd_tl
 \tl_clear:N \l_tzaxesL_name_path_tl
 \tl_clear:N \l_tzaxesL_shift_coor_tl

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tl_set:Nn \l_tzaxesL_opt_tl { [ #2 ] }

 \tl_set:Nn \l_tzaxesL_name_path_tl { #4 }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tzaxesL_shift_coor_tl { #3 }
   \bool_set_true:N \l_tzaxesL_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzaxesL_shift_coor_tl
   \bool_set_false:N \l_tzaxesL_shift_coor_bool
 }

 \tzaxesL_check_token:n
}

\cs_new:Npn \tzaxesL_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
 { \tzaxesL_final_actions ( }
}

\NewDocumentCommand\tzaxesL_final_actions{ r() r() +G{} O{} +G{} O{} }
{
 \bool_if:NTF \l_tmpa_bool
 { %% swap version
   % x-axis
   \bool_if:NTF \l_tzaxesL_shift_coor_bool
   {
     \tl_set:Nx \l_tzaxesL_x_cmd_tl
     {
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 |- #2 )
       node [ left , \exp_not:n { #4 }  ] { \exp_not:n { #3 } }
     }
   }
   {
     \tl_set:Nn \l_tzaxesL_x_cmd_tl
     {
       ( #2 ) -- ( #1 |- #2 )
       node [ left , #4 ] { #3 }
     }
   }
   % y-axis
   \bool_if:NTF \l_tzaxesL_shift_coor_bool
   {
     \tl_set:Nx \l_tzaxesL_y_cmd_tl
     {
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 |- #1 )
       node [ below , \exp_not:n { #6 } ] { \exp_not:n { #5 } }
     }
   }
   {
     \tl_set:Nn \l_tzaxesL_y_cmd_tl
     {
       ( #2 ) -- ( #2 |- #1 )
       node [ below , #6] { #5 }
     }
   }
   % for path only
   \bool_if:NTF \l_tzaxesL_shift_coor_bool
   {
     \tl_set:Nx \l_tzaxesL_path_cmd_tl
     {
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 |- #2 )
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 |- #1 )
     }
   }
   {
     \tl_set:Nn \l_tzaxesL_path_cmd_tl
     {
       ( #2 ) -- ( #1 |- #2 )
       ( #2 ) -- ( #2 |- #1 )
     }
   }
 }
 { %% standard version
   % x-axis
   \bool_if:NTF \l_tzaxesL_shift_coor_bool
   {
     \tl_set:Nx \l_tzaxesL_x_cmd_tl
     {
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 )
       -- ( [shift = {(\l_tzaxesL_shift_coor_tl) } ] #2 |- #1 )
       node [ right , \exp_not:n { #4 } ] { \exp_not:n { #3 } }
     }
   }
   {
     \tl_set:Nn \l_tzaxesL_x_cmd_tl
     {
       ( #1 ) -- ( #2 |- #1 )
       node [ right , #4 ] { #3 }
     }
   }
   % y-axis
   \bool_if:NTF \l_tzaxesL_shift_coor_bool
   {
     \tl_set:Nx \l_tzaxesL_y_cmd_tl
     {
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 |- #2 )
       node [ above , \exp_not:n { #6 } ] { \exp_not:n { #5 } }
     }
   }
   {
     \tl_set:Nn \l_tzaxesL_y_cmd_tl
     {
       ( #1 ) -- ( #1 |- #2 )
       node [ above , #6 ] { #5 }
     }
   }
   % path only
   \bool_if:NTF \l_tzaxesL_shift_coor_bool
   {
     \tl_set:Nx \l_tzaxesL_path_cmd_tl
     {
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #2 |- #1 )
       ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 )
       -- ( [ shift = { (\l_tzaxesL_shift_coor_tl) } ] #1 |- #2 )
     }
   }
   {
     \tl_set:Nn \l_tzaxesL_path_cmd_tl
     {
       ( #1 ) -- ( #2 |- #1 )
       ( #1 ) -- ( #1 |- #2 )
     }
   }
 }
 % combining options and command tokens
 \tl_put_left:No \l_tzaxesL_x_cmd_tl { \l_tzaxesL_opt_tl }
 \tl_put_left:No \l_tzaxesL_y_cmd_tl { \l_tzaxesL_opt_tl }
 \tl_put_left:No \l_tzaxesL_path_cmd_tl
   { [ name~path = \l_tzaxesL_name_path_tl ] }
 % final actions
 \exp_last_unbraced:Nf \draw \l_tzaxesL_x_cmd_tl ;
 \exp_last_unbraced:Nf \draw \l_tzaxesL_y_cmd_tl ;
 \exp_last_unbraced:Nf \path \l_tzaxesL_path_cmd_tl ;
}

%%% -- end of \tzaxesL



%%% \tzaxisx

\NewDocumentCommand\tzaxisx{ s O{} D<>{0} D""{axisx} m m G{} O{} }
{
 \draw [ -> , name~path = #4 , #2 ]
   ( #5 , #3 ) -- ( #6 , #3 ) node [ right , #8 ] { #7 } ;
}


%%% \tzaxisy

\NewDocumentCommand\tzaxisy{ s O{} D<>{0} D""{axisy} m m G{} O{} }
{
 \draw [ -> , name~path = #4 , #2 ]
   ( #3 , #5 ) -- ( #3 , #6 ) node [ above , #8 ] { #7 } ;
}


%%%%% Ticks

%%% \tztikcs : (combine \tzticksx and \tzticksy)

\use:x{
 \NewDocumentCommand \exp_not:N \tzticks
 { s O{} D<>{0,0}
     >{ \SplitArgument {1} { \tl_to_str:n {:} } } d() m O{}
     >{ \SplitArgument {1} { \tl_to_str:n {:} } } d() G{} O{}
 }
}
{
 \tzgetxyval(#3){\tzticksXshift}{\tzticksYshift}
 \IfValueT { #4 } { \tzticks_Xlength_process #4 }
 %% ------
 \IfValueT { #7 } { \tzticks_Ylength_process #7 }

 \IfBooleanTF { #1 }
 {
   \IfNoValueT { #4 }
   {
     \def\tzticksXFromVal{0pt}
     \def\tzticksXToVal{3pt}
   }
   \foreach \xx / \tzXtext in { #5 }
     \draw [ shift = {(0,\tzticksYshift)} , #2 ]
           (\xx , \tzticksXFromVal)
        -- (\xx , \tzticksXToVal)   ; % ignores \txXtext
   %% --------
   \IfNoValueT { #7 }
   {
     \def\tzticksYFromVal{0pt}
     \def\tzticksYToVal{3pt}
   }
   \foreach \yy/\tzYtext in { #8 }
     \draw [ shift = {(\tzticksXshift,0)} , #2 ]
           (\tzticksYFromVal , \yy)
        -- (\tzticksYToVal , \yy)   ; % ignores \txXtext
 }
 {
   \IfNoValueT { #4 }
   {
     \def\tzticksXFromVal{0pt}
     \def\tzticksXToVal{0pt}
   }
   \foreach \xx / \tzXtext in { #5 }
     \draw [ shift = {(0,\tzticksYshift)} , #2 ]
           (\xx ,\tzticksXFromVal)
        -- (\xx , \tzticksXToVal)
           (\xx , 0 ) node
             [ text~height = 1.25ex ,
               text~depth = .25ex ,
               below , #6 ] {\tzXtext} ;
   %% --------
   \IfNoValueT { #7 }
   {
     \def\tzticksYFromVal{0pt}
     \def\tzticksYToVal{0pt}
   }
   \foreach \yy / \tzYtext in { #8 }
     \draw [ shift = {(\tzticksXshift,0)} , #2 ]
           (\tzticksYFromVal , \yy)
        -- (\tzticksYToVal , \yy)
           (0 , \yy)
           node [ left , #9 ] { \tzYtext } ;
 }
}

\NewDocumentCommand\tzticks_Xlength_process { m m }
{
 \def\tzticksXFromVal{#1}
 \def\tzticksXToVal{#2}
}
%% --------
\NewDocumentCommand\tzticks_Ylength_process { m m }
{
 \def\tzticksYFromVal{#1}
 \def\tzticksYToVal{#2}
}

%%% --- end of \tzticks


%%% \tztikcsx (main)
%% -- ticks and labels along the x axis

\use:x{
 \NewDocumentCommand \exp_not:N \tzticksx
 { s O{} D<>{0}
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } d() m O{}
 }
}
{
 \IfValueT { #4 } { \tzticksx_length_process #4 }

 \IfBooleanTF { #1 }
 {
   \IfNoValueT { #4 }
   {
     \def\tzticksxFromVal{0pt}
     \def\tzticksxToVal{3pt}
   }
   \foreach \xx / \tzxtext in { #5 }
     \draw [ shift = {(0,#3)} , #2 ]
           (\xx , \tzticksxFromVal)
        -- (\xx , \tzticksxToVal)   ;
 }
 {
   \IfNoValueT { #4 }
   {
     \def\tzticksxFromVal{0pt}
     \def\tzticksxToVal{0pt}
   }
   \foreach \xx / \tzxtext in { #5 }
     \draw [ shift = {(0,#3)} , #2 ]
           (\xx ,\tzticksxFromVal)
        -- (\xx , \tzticksxToVal)
           (\xx , 0 ) node
             [ text~height = 1.25ex ,
               text~depth = .25ex ,
               below , #6 ] {\tzxtext} ;

 }
}

\NewDocumentCommand\tzticksx_length_process { m m }
{
 \def\tzticksxFromVal{#1}
 \def\tzticksxToVal{#2}
}

%%% --- end of \tzticksx


%%% \tztikcsy (main)
%% -- ticks and labels along with the y axis

\use:x{
 \NewDocumentCommand \exp_not:N \tzticksy
 { s O{} D<>{0}
   >{ \SplitArgument {1} { \tl_to_str:n {:} } } d() m O{}
 }
}
{

 \IfValueT { #4 } { \tzticksy_length_process #4 }

 \IfBooleanTF { #1 }
 {
   \IfNoValueT { #4 }
   {
     \def\tzticksyFromVal{0pt}
     \def\tzticksyToVal{3pt}
   }
   \foreach \yy/\tzytext in { #5 }
     \draw [ shift = {(#3,0)} , #2 ]
           (\tzticksyFromVal , \yy)
        -- (\tzticksyToVal , \yy)   ;
 }
 {
   \IfNoValueT { #4 }
   {
     \def\tzticksyFromVal{0pt}
     \def\tzticksyToVal{0pt}
   }
   \foreach \yy / \tzytext in { #5 }
     \draw [ shift = {(#3,0)} , #2 ]
           (\tzticksyFromVal , \yy)
        -- (\tzticksyToVal , \yy)
           (0 , \yy)
           node [ left , #6 ] { \tzytext } ;
 }
}

\NewDocumentCommand\tzticksy_length_process { m m }
{
 \def\tzticksyFromVal{#1}
 \def\tzticksyToVal{#2}
}

%%% --- end of \tzticksy


%%%%% Projections
%% lines and tick labels of projection onto x/y axis

%%% \tzproj

\NewDocumentCommand\tzproj
 { s O{} d<> r() G{} O{} G{} O{} D(){\tz@initial@dot@size} }
{
 \IfValueTF { #3 }
 { \coordinate (tzProj) at (#3)  ; }
 { \coordinate (tzProj) at (0,0) ; }
 \draw [ dotted , #2 ]
       (#4 |- tzProj)
       node [ text~height = 1.25ex ,
               text~depth = .25ex ,
               below , #6 ] { #5 }
    -- (#4) -- (tzProj |- #4)
       node [ left , #8 ] { #7 } ;
 \IfBooleanT {#1} { \tzdot*(#4)(#9) }
}

%%% \tzprojs : semicolon version

%\bool_new:N \l_tzprojs_shift_coor_bool

%%% \tzprojs (main)
\NewDocumentCommand\tzprojs { s O{} d<> }
{
 \tl_clear:N \l_tzprojs_cmd_tl
%  \tl_clear:N \l_tzprojs_opt_tl
 \tl_clear:N \l_tzprojs_coors_tl

 \IfValueTF { #3 }
 { \coordinate (tzProjs) at (#3)  ; }
 { \coordinate (tzProjs) at (0,0) ; }

 \tl_put_right:Nn \l_tzprojs_cmd_tl { [ dotted , #2 ] }

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzprojs_check_token:n
}

\cs_new:Npn \tzprojs_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzprojs_sub_fn #1 }
%  { \tzprojs_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzprojs_sub_fn #1 }
   { ; } { \tzprojs_stop_action }
 }
 {
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzprojs_sub_fn { r() G{} O{} G{} O{} }
{
 % collect only coordinates (to print dots)
 \tl_put_right:Nn \l_tzprojs_coors_tl { (#1) }
 % collect cmd_tl (for all inputs)
 \tl_put_right:Nn \l_tzprojs_cmd_tl
 {
   (#1 |- tzProjs)
   node [ text~height = 1.25ex ,
          text~depth = .25ex ,
          below , #3 ] { #2 }
   -- (#1) -- (tzProjs |- #1)
   node [ left , #5 ] { #4 }
 }

 \tzprojs_check_token:n
}

\NewDocumentCommand\tzprojs_stop_action { D(){\tz@initial@dot@size} }
{
 % final action
 \exp_last_unbraced:Nf \draw \l_tzprojs_cmd_tl ;
 \bool_if:NT \l_tmpa_bool
 { \exp_last_unbraced:NNf \tzdots* \l_tzprojs_coors_tl ; (#1) }
}
%%% --- end of \tzprojs


%%% \tzprojx

\NewDocumentCommand\tzprojx
 { s O{} d<> r() G{} O{} D(){\tz@initial@dot@size} }
{
 \IfValueTF { #3 }
 { \coordinate (tzProjx) at (#3)  ; }
 { \coordinate (tzProjx) at (0,0) ; }
 \draw [ dotted , #2 ] (#4)
    -- (#4 |- tzProjx)
       node [ text~height = 1.25ex ,
              text~depth = .25ex ,
              below , #6 ] { #5 } ;
 \IfBooleanT { #1 } { \tzdot*(#4)(#7) }
}

%%% \tzprojy

\NewDocumentCommand\tzprojy
 { s O{} d<> r() G{} O{} D(){\tz@initial@dot@size} }
{
 \IfValueTF { #3 }
 { \coordinate (tzProjy) at (#3)  ; }
 { \coordinate (tzProjy) at (0,0) ; }
 \draw [ dotted , #2 ] (#4)
    -- (#4 -| tzProjy)
       node [ left , #6 ] { #5 } ;
 \IfBooleanT { #1 } { \tzdot*(#4)(#7) }
}

%%% \tzprojsx : semicolon version

%\bool_new:N \l_tzprojsx_shift_coor_bool

%%% \tzprojsx (main)
\NewDocumentCommand\tzprojsx { s O{} d<> }
{
 \tl_clear:N \l_tzprojsx_cmd_tl
%  \tl_clear:N \l_tzprojsx_opt_tl
 \tl_clear:N \l_tzprojsx_coors_tl

 \IfValueTF { #3 }
 { \coordinate (tzProjsx) at (#3)  ; }
 { \coordinate (tzProjsx) at (0,0) ; }

 \tl_put_right:Nn \l_tzprojsx_cmd_tl { [ dotted , #2 ] }

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzprojsx_check_token:n
}

\cs_new:Npn \tzprojsx_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzprojsx_sub_fn #1 }
%  { \tzprojsx_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzprojsx_sub_fn #1 }
   { ; } { \tzprojsx_stop_action }
 }
 {
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzprojsx_sub_fn { r() G{} O{} }
{
 % collect only coordinates (to print dots)
 \tl_put_right:Nn \l_tzprojsx_coors_tl { (#1) }
 % collect cmd_tl (for all inputs)
 \tl_put_right:Nn \l_tzprojsx_cmd_tl
 {
   (#1) -- (#1 |- tzProjsx)
   node [ text~height = 1.25ex ,
          text~depth = .25ex ,
          below , #3 ] { #2 }
 }

 \tzprojsx_check_token:n
}

\NewDocumentCommand\tzprojsx_stop_action { D(){\tz@initial@dot@size} }
{
 % final action
 \exp_last_unbraced:Nf \draw \l_tzprojsx_cmd_tl ;
 \bool_if:NT \l_tmpa_bool
 { \exp_last_unbraced:NNf \tzdots* \l_tzprojsx_coors_tl ; (#1) }
}
%%% --- end of \tzprojsx


%%% \tzprojsy : semicolon version

%\bool_new:N \l_tzprojsy_shift_coor_bool

%%% \tzprojsy (main)
\NewDocumentCommand\tzprojsy { s O{} d<> }
{
 \tl_clear:N \l_tzprojsy_cmd_tl
%  \tl_clear:N \l_tzprojsy_opt_tl
 \tl_clear:N \l_tzprojsy_coors_tl

 \IfValueTF { #3 }
 { \coordinate (tzProjsy) at (#3)  ; }
 { \coordinate (tzProjsy) at (0,0) ; }

 \tl_put_right:Nn \l_tzprojsy_cmd_tl { [ dotted , #2 ] }

 \IfBooleanTF { #1 }
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \tzprojsy_check_token:n
}

\cs_new:Npn \tzprojsy_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tzprojsy_sub_fn #1 }
%  { \tzprojsy_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tzprojsy_sub_fn #1 }
   { ; } { \tzprojsy_stop_action }
 }
 {
   \msg_error:nn { tzplot } { semicolon-error }
 }
}

\NewDocumentCommand\tzprojsy_sub_fn { r() G{} O{} }
{
 % collect only coordinates (to print dots)
 \tl_put_right:Nn \l_tzprojsy_coors_tl { (#1) }
 % collect cmd_tl (for all inputs)
 \tl_put_right:Nn \l_tzprojsy_cmd_tl
 {
   (#1) -- (#1 -| tzProjsy)
   node [ left , #3 ] { #2 }
 }

 \tzprojsy_check_token:n
}

\NewDocumentCommand\tzprojsy_stop_action { D(){\tz@initial@dot@size} }
{
 % final action
 \exp_last_unbraced:Nf \draw \l_tzprojsy_cmd_tl ;
 \bool_if:NT \l_tmpa_bool
 { \exp_last_unbraced:NNf \tzdots* \l_tzprojsy_coors_tl ; (#1) }
}
%%% --- end of \tzprojsy


%%%%% Nodes

%%% \tznode -- putting texts (and labels as option)

\NewDocumentCommand\tznode{ s O{} d<> r() D(){tzNodeName} +m O{} D<>{} }
{
 \IfBooleanTF { #1 }
 {
   \IfValueTF { #3 }
   { \node #8 [ draw , #2 ] (#5) at ([shift={(#3)}]#4) [ #7 ] { #6 } ; }
   { \node #8 [ draw , #2 ] (#5) at (#4) [ #7 ] { #6 } ; }
 }
 {
   \IfValueTF { #3 }
   { \node #8 [        #2 ] (#5) at ([shift={(#3)}]#4) [ #7 ] { #6 } ; }
   { \node #8 [        #2 ] (#5) at (#4) [ #7 ] { #6 } ; }
 }
}
%%% --- end of \tznode


%%% \tznodes
%%% repeat pattern: (coor)(nodename){label}[pos]

%\tl_new:N \l_tznodes_opt_tl
%\tl_new:N \l_tznodes_cmd_tl
\bool_new:N \l_tznodes_shift_coor_bool

%%% \tznodes (main)
\NewDocumentCommand\tznodes{ s O{} d<> }
{
 \tl_clear:N \l_tznodes_cmd_tl

 \IfBooleanTF { #1 }
 {
   \tl_set:Nn \l_tznodes_cmd_tl { [ every~node/.style = { draw , #2 } ] }
 }
 {
   \tl_set:Nn \l_tznodes_cmd_tl { [ every~node/.style = {        #2 } ] }
 }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tznodes_shift_coor_tl { #3 }
   \bool_set_true:N \l_tznodes_shift_coor_bool
 }
 {
   \tl_clear:N \l_tznodes_shift_coor_tl
   \bool_set_false:N \l_tznodes_shift_coor_bool
 }

 \tznodes_check_token:n
}

\cs_new:Npn \tznodes_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tznodes_sub_fn #1 }
%  { \tznodes_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tznodes_sub_fn #1 }
   { ; } { \tznodes_late_opt_fn }
 }
 {
%    \tznodes_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}


\NewDocumentCommand\tznodes_sub_fn { r() r() +G{} O{} }
{
 \bool_if:NTF \l_tznodes_shift_coor_bool
 {
   \tl_put_right:Nx \l_tznodes_cmd_tl
   {% if shift
     ( [ shift = { (\l_tznodes_shift_coor_tl) } ] #1 )
   }
 }
 { \tl_put_right:Nn \l_tznodes_cmd_tl { (#1) } }

 \tl_put_right:Nn \l_tznodes_cmd_tl { node (#2) }  %% node (name)
 \tl_put_right:Nn \l_tznodes_cmd_tl
 { [ #4 ] { #3 } }
 \tznodes_check_token:n
}

\NewDocumentCommand\tznodes_late_opt_fn { D<>{} }
{
 % #1 does nothing (kept for consistency with \tznodedots)
 \tznodes_stop_action
}


\NewDocumentCommand\tznodes_stop_action {}
{
 \exp_last_unbraced:Nf \path \l_tznodes_cmd_tl ;
}

%%% --- end of \tznodes



%%% \tznodedot (main)

\NewDocumentCommand\tznodedot
 { s O{} d<> r() D(){tzNodeName} +G{} >{\TrimSpaces}o D(){\tz@initial@dot@size} }
{
 \tl_clear:N \l_tznodedot_cmd_tl

 \renewcommand\tzdotsize{ #8 }

%%%%%% to use string replacement for label positions
 \IfValueTF { #7 }
 {
       \tl_if_in:nnTF { #7 } { [ }
   { \extract_posopt:w #7 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #7 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #7 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \IfValueTF { #3 }
 {% if shift
   \tl_put_right:Nn \l_tznodedot_cmd_tl
     { ([shift={(#3)}]#4) node (#5) }
 }
 {% no shift (normal)
   \tl_put_right:Nn \l_tznodedot_cmd_tl
     { (#4) node (#5) }
 }
 \IfBooleanTF { #1 }
 {
   \tl_put_right:Nn \l_tznodedot_cmd_tl { [ tzdot , fill , }
 }
 {
   \tl_put_right:Nn \l_tznodedot_cmd_tl { [ tzdot , }
 }
 \tl_put_right:Nx \l_tznodedot_cmd_tl
   {
     label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #6 } } , % str_opt
   }
 \tl_put_right:Nn \l_tznodedot_cmd_tl
   {
     minimum~size = \tzdotsize , #2 ] {}
   }
 \exp_last_unbraced:Nf \path \l_tznodedot_cmd_tl ;
}

%%% --- end of \tznodedot


%%% \tznodedots
%%% repeat pattern: (coor)(nodename){label}[pos]

\tl_new:N \l_tznodedots_opt_tl
\tl_new:N \l_tznodedots_cmd_tl
\bool_new:N \l_tznodedots_shift_coor_bool

%%% \tznodedots (main)
\NewDocumentCommand\tznodedots{ s O{} d<> }
{
 \tl_clear:N \l_tznodedots_cmd_tl

 \IfBooleanTF { #1 }
 { \tl_set:Nn \l_tznodedots_STYLE_fill_tl { fill } }
 { \tl_set:Nn \l_tznodedots_STYLE_fill_tl { fill = none } }

 \tl_if_empty:nTF { #2 }
 { \tl_set:Nn \l_tznodedots_opt_tl { tzdot } }
 { \tl_set:Nn \l_tznodedots_opt_tl { tzdot , #2 } }

 \IfValueTF { #3 }
 {
   \tl_set:Nn \l_tznodedots_shift_coor_tl { #3 }
   \bool_set_true:N \l_tznodedots_shift_coor_bool
 }
 {
   \tl_clear:N \l_tznodedots_shift_coor_tl
   \bool_set_false:N \l_tznodedots_shift_coor_bool
 }

 \tznodedots_check_token:n
}

\cs_new:Npn \tznodedots_check_token:n #1
{
%  \token_if_eq_charcode:NNTF #1 (
%  { \tznodedots_sub_fn #1 }
%  { \tznodedots_stop_action }
 \str_case:nnF { #1 }
 {
   { ( } { \tznodedots_sub_fn #1 }
   { ; } { \tznodedots_late_opt_fn }
 }
 {
%    \tznodedots_stop_action
   \msg_error:nn { tzplot } { semicolon-error }
 }
}


\NewDocumentCommand\tznodedots_sub_fn { r() r() +G{} >{\TrimSpaces}o }
{
%%%%%% to use string replacement for label positions
 \IfValueTF { #4 }
 {
       \tl_if_in:nnTF { #4 } { [ }
   { \extract_posopt:w #4 \q_stop } % ndh
       {
         \tl_set:Nx \l_label_pos_str_trimmed_tl { \tl_trim_spaces:n { #4 } }
     \str_case_e:nnF { \l_label_pos_str_trimmed_tl }
     {
       {l} { \tl_set:Nn \l_label_pos_str_tl {left} }
       {r} { \tl_set:Nn \l_label_pos_str_tl {right} }
       {a} { \tl_set:Nn \l_label_pos_str_tl {above} }
       {b} { \tl_set:Nn \l_label_pos_str_tl {below} }
       {c} { \tl_set:Nn \l_label_pos_str_tl {center} }
       {al} { \tl_set:Nn \l_label_pos_str_tl {above~left} }
       {ar} { \tl_set:Nn \l_label_pos_str_tl {above~right} }
       {bl} { \tl_set:Nn \l_label_pos_str_tl {below~left} }
       {br} { \tl_set:Nn \l_label_pos_str_tl {below~right} }
     }
     {
       \tl_set:Nn \l_label_pos_str_tl { #4 }
     }
   }
 }
 {
   \tl_clear:N \l_label_pos_str_tl
 }
%%%%%%%%%%

 \bool_if:NTF \l_tznodedots_shift_coor_bool
 {
   \tl_put_right:Nx \l_tznodedots_cmd_tl
   {% if shift
     ( [ shift = { (\l_tznodedots_shift_coor_tl) } ] #1 )
   }
 }
 { \tl_put_right:Nn \l_tznodedots_cmd_tl { (#1) } }

 \tl_put_right:Nn \l_tznodedots_cmd_tl { node (#2) }  %% node (name)

 \tl_put_right:Nx \l_tznodedots_cmd_tl
 {
   [
     \l_tznodedots_STYLE_fill_tl ,
     minimum~size = \exp_not:n { \tzdotsize } ,
     label = { \l_label_pos_str_tl \c_colon_str \exp_not:n { #3 } } , % pos_str
 }
 \tl_put_right:No \l_tznodedots_cmd_tl   % expand `once'
 {
     \l_tznodedots_opt_tl
   ] {}
 }
 \tznodedots_check_token:n
}

\NewDocumentCommand\tznodedots_late_opt_fn { D(){\tz@initial@dot@size} }
{
 \renewcommand\tzdotsize{ #1 }

 \tznodedots_stop_action
}


\NewDocumentCommand\tznodedots_stop_action {}
{
 \exp_last_unbraced:Nf \path \l_tznodedots_cmd_tl ;
}

%%% --- end of \tznodedots



%%% \tznodeframe

\NewDocumentCommand\tznodeframe
 { s O{} d<> r() D(){tzNodeName} +G{} O{} G{\tz@initial@fill@opacity} }
{
 \renewcommand\tzfillopacity{#8}
 \IfBooleanTF { #1 }
 {
   \node [
           draw , rectangle ,
           fill ,
           fill~opacity = \tzfillopacity , text~opacity = 1 ,
           #2
         ]
     (#5) at \IfValueTF { #3 } { ([shift={(#3)}]#4) } { (#4) }
     [ draw = black , text = black , #7 ] { #6 } ;
 }
 {
   \node [ draw , rectangle , #2 ]
     (#5) at \IfValueTF { #3 } { ([shift={(#3)}]#4) } { (#4) }
     [ text = black , #7 ] { #6 } ;
 }
}


%%% \tznodebox  \tznoderectangle
\let\tznodebox\tznodeframe
\let\tznoderectangle\tznodeframe


%%% \tznodecircle

\NewDocumentCommand\tznodecircle
 { s O{} d<> r() D(){tzNodeName} +G{} O{} G{\tz@initial@fill@opacity} }
{
 \renewcommand\tzfillopacity{#8}
 \IfBooleanTF { #1 }
 {
   \node [
           draw , circle ,
           fill ,
           fill~opacity = \tzfillopacity , text~opacity = 1 ,
           #2
         ]
     (#5) at \IfValueTF { #3 } { ([shift={(#3)}]#4) } { (#4) }
     [ draw = black , text = black , #7 ] { #6 } ;
 }
 {
   \node [ draw , circle , #2 ]
     (#5) at \IfValueTF { #3 } { ([shift={(#3)}]#4) } { (#4) }
     [ text = black , #7 ] { #6 } ;
 }
}

%%% \tznodeellipse

\NewDocumentCommand\tznodeellipse
 { s O{} d<> r() D(){tzNodeName} +G{} O{} G{\tz@initial@fill@opacity} }
{
 \renewcommand\tzfillopacity{#8}
 \IfBooleanTF { #1 }
 {
   \node [
           draw , ellipse ,
           fill ,
           fill~opacity = \tzfillopacity , text~opacity = 1 ,
           #2
         ]
     (#5) at \IfValueTF { #3 } { ([shift={(#3)}]#4) } { (#4) }
     [ draw = black , text = black , #7 ] { #6 } ;
 }
 {
   \node [ draw , ellipse , #2 ]
     (#5) at \IfValueTF { #3 } { ([shift={(#3)}]#4) } { (#4) }
     [ text = black , #7 ] { #6 } ;
 }
}

%%% \tznodeoval
\let\tznodeoval\tznodeellipse



%%%%% Secant lines

%% secant line

%%% \tzsecantat (main)

\use:x{
 \NewDocumentCommand \exp_not:N \tzsecantat
 { s O{} d<> D""{} m m m
   >{ \SplitArgument { 1 } { \tl_to_str:n {:} } } o
 }
}
{
 \tl_clear:N \l_tzsecantat_cmd_tl

 \IfBooleanTF { #1 }  % NOT USED!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 % define two points
 \tzvXpointat{#5}{#6}(LX-point) % vertical X point
 \tzvXpointat{#5}{#7}(RX-point) % vertical X point

 % collect cmd_tl

 \IfNoValueTF { #8 }
 {
   \IfValueTF { #3 }
   {% if shift
     \tl_put_right:Nn \l_tzsecantat_cmd_tl
     {
       [ name~path = #4 , #2 ]
       ([ shift = { (#3) } ]LX-point) -- ([ shift = { (#3) } ]RX-point)
     }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzsecantat_cmd_tl
     {
       [ name~path = #4 , #2 ]
       (LX-point) -- (RX-point)
     }
   }
 }
 {
   \tzsecantat_domain_process #8
   \tzgetxyval(LX-point){\tzTANLLX}{\tzTANLLY}
   \tzgetxyval(RX-point){\tzTANRRX}{\tzTANRRY}

   \edef\tzTANSlope{(\tzTANRRY-\tzTANLLY)/(\tzTANRRX-\tzTANLLX)}
   \def\tzsecantatLFn{\tzTANSlope*(\x-\tzTANLLX)+\tzTANLLY}

   \IfValueTF { #3 }
   {% shift
     \tl_put_right:Nn \l_tzsecantat_cmd_tl
     {
       [ name~path = #4 ,
         shift = { (#3) } ,
     }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzsecantat_cmd_tl
     {
       [ name~path = #4 ,
     }
   }

   \tl_put_right:Nx \l_tzsecantat_cmd_tl
   {
         domain = \tzsecantatFromVal \c_colon_str \tzsecantatToVal ,
   }
   \tl_put_right:Nn \l_tzsecantat_cmd_tl
   {
         #2 ]
     plot ( \x , { \tzsecantatLFn } ) % \x should not be expanded
   }
 }

%  \tzsecantat_sub_fn:n
 \tzsecantat_final_actions
}

\NewDocumentCommand\tzsecantat_domain_process{ m m }
{
 \def\tzsecantatFromVal{#1}
 \def\tzsecantatToVal{#2}
}

%\cs_new:Npn \tzsecantat_sub_fn:n
%{
%  \tzsecantat_final_actions
%}

\NewDocumentCommand\tzsecantat_final_actions { +G{} O{} D<>{} }
{
 \begin{pgfonlayer}{\tzsecantlayer}
 \exp_last_unbraced:Nf \draw \l_tzsecantat_cmd_tl node [ #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tzsecantat_cmd_tl ;
}

%%% --- end of \tzsecantat


%%% \tzsecant (main)

\use:x{
 \NewDocumentCommand \exp_not:N \tzsecant
 { s O{} d<> d"" m r() r()
   >{ \SplitArgument { 1 } { \tl_to_str:n {:} } } o
 }
}
{
 \tl_clear:N \l_tzsecant_cmd_tl

 \IfBooleanTF { #1 }  % NOT USED!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 % define two points
 \tzvXpoint{#5}(#6)(LX-point) % vertical X point
 \tzvXpoint{#5}(#7)(RX-point) % vertical X point

 % collect cmd_tl
 \IfNoValueTF { #8 }
 {
   \IfValueTF { #3 }
   {% if shift
     \tl_put_right:Nn \l_tzsecant_cmd_tl
     {
       [ name~path = #4 , #2 ]
       ([ shift = { (#3) } ]LX-point) -- ([ shift = { (#3) } ]RX-point)
     }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzsecant_cmd_tl
     {
       [ name~path = #4 , #2 ]
       (LX-point) -- (RX-point)
     }
   }
 }
 {
   \tzsecant_domain_process #8
   \tzgetxyval(LX-point){\tzTANLLX}{\tzTANLLY}
   \tzgetxyval(RX-point){\tzTANRRX}{\tzTANRRY}

   \edef\tzTANSlope{(\tzTANRRY-\tzTANLLY)/(\tzTANRRX-\tzTANLLX)}
   \def\tzsecantLFn{\tzTANSlope*(\x-\tzTANLLX)+\tzTANLLY}

   \IfValueTF { #3 }
   {% shift
     \tl_put_right:Nn \l_tzsecant_cmd_tl
     {
       [ name~path = #4 ,
         shift = { (#3) } ,
     }
   }
   {% no shift (normal)
     \tl_put_right:Nn \l_tzsecant_cmd_tl
     {
       [ name~path = #4 ,
     }
   }

   \tl_put_right:Nx \l_tzsecant_cmd_tl
   {
         domain = \tzsecantFromVal \c_colon_str \tzsecantToVal ,
   }
   \tl_put_right:Nn \l_tzsecant_cmd_tl
   {
         #2 ]
     plot ( \x , { \tzsecantLFn } ) % \x should not be expanded
   }
 }

%  \tzsecant_sub_fn:n
 \tzsecant_final_actions
}

\NewDocumentCommand\tzsecant_domain_process{ m m }
{
 \def\tzsecantFromVal{#1}
 \def\tzsecantToVal{#2}
}

%\cs_new:Npn \tzsecant_sub_fn:n
%{
%  \tzsecant_final_actions
%}

\NewDocumentCommand\tzsecant_final_actions { +G{} O{} D<>{} }
{
 \begin{pgfonlayer}{\tzsecantlayer}
 \exp_last_unbraced:Nf \draw \l_tzsecant_cmd_tl node [ #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tzsecant_cmd_tl ;
}

%%% --- end of \tzsecant


%%%%% Slope and Tangent

%%% to **resolve** the discrepancy issue due to bounding box
%%% for \tzslope(at) and \tztangent(at)
%%% (ndh)

\NewDocumentCommand \IfNodeDefined { m m m }
{
 \@ifundefined{pgf@sh@ns@#1}
 {#3}
 {#2}
}

\AddToHook{env/tikzpicture/before}{%
 \@ifundefined{pgf@sh@ns@bbxBottom}
 {}
 { \cs_undefine:N \pgf@sh@ns@bbxBottom }
 \def\TANCurve{} \def\TANWhere{}
}
%\AddToHook{env/tikzpicture/before}{%
%  \@ifundefined{pgf@sh@ns@bbxBottom}
%  {}
%  { \cs_undefine:N \pgf@sh@ns@bbxBottom }
%}

%%% Do not forget to declare, before final action,
%%% \gdef\TANCurve{<#m>}\gdef\TANWhere{<#n>}


%%%%% Slope lines
%% No <shift coor>
%% No <shift coor>
%% No <shift coor>

%%% \tzslopeat
%% -- slope line at x

\bool_new:N \l_tzslopeat_bbox_bool

%%% \tzslopeat (main)
\NewDocumentCommand\tzslopeat
 { t' O{} m m
   >{ \SplitArgument { 1 } { , } } d()
   m O{0} % +G{} O{} D<>{}
 }
{
 % to resolve discrepancy (due to bounding box), when repeated
 \bool_if:nTF
 {
   \str_if_eq_p:ee { \TANCurve } { #3 } &&
       \str_if_eq_p:ee { \TANWhere } { #4 }
       }
       { \bool_set_true:N \l_tzslopeat_bbox_bool }
       { \bool_set_false:N \l_tzslopeat_bbox_bool }

 % for local change of epsilon_1, epsilon_2
 \IfValueT { #5 }
 {
   \tzslopeat_epsilon_process #5
   \renewcommand\tzslopeepsilonL{\tzslopeatEpsilonOne}
   \renewcommand\tzslopeepsilonR{\tzslopeatEpsilonTwo}
 }

 % getting ready
 \coordinate (LXcoor) at ($(#4,0)-(\tzslopeepsilonL,0)$) ;
 \coordinate (RXcoor) at ($(#4,0)+(\tzslopeepsilonR,0)$) ;

 \bool_if:NTF \l_tzslopeat_bbox_bool
 {
   \IfNodeDefined{bbxBottom}{}
   {
     \coordinate (bbxTop)    at (current~bounding~box.north) ;
     \coordinate (bbxBottom) at (current~bounding~box.south) ;
   }
 }
 {
   \coordinate (bbxTop)    at (current~bounding~box.north) ;
   \coordinate (bbxBottom) at (current~bounding~box.south) ;
 }

 % find vertical X points
 \path [ name~path = C-vline ] (#4,0 |- bbxBottom) -- (#4,0 |- bbxTop) ;
 \path [ name~intersections = { of = #3 ~ and ~ C-vline , name = TANp } ] ;

 \path [ name~path = L-vline ] (LXcoor |- bbxBottom) -- (LXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #3 ~ and ~ L-vline , name = LXcut } ] ;

 \path [ name~path = R-vline ] (RXcoor |- bbxBottom) -- (RXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #3 ~ and ~ R-vline , name = RXcut } ] ;

 % move to tangent point
 \coordinate (tzXproj)
   at ($(LXcut-1)!(TANp-1)!(RXcut-1)$); % projection
 \coordinate (LLpoint)
   at ($(LXcut-1)+(TANp-1)-(tzXproj)$); % move
 \coordinate (RRpoint)
   at ($(RXcut-1)+(TANp-1)-(tzXproj)$); % move

 % determine final extended points
 \tl_set:Nx \l_tmpa_tl
 {
   \IfBooleanTF { #1 }
   {
     (RRpoint) -- (TANp-1) --
     ([turn]-180 \c_colon_str #6/2 ) coordinate (final-LL)
   }
   {
     (RRpoint) -- (TANp-1) --
     ([turn]#7 \c_colon_str #6/2 ) coordinate (final-LL)
   }
 }
 \tl_set:Nx \l_tmpb_tl
 {
   \IfBooleanTF { #1 }
   {
     (LLpoint) -- (TANp-1) --
     ([turn]-180 \c_colon_str #6/2 ) coordinate (final-RR)
   }
   {
     (LLpoint) -- (TANp-1) --
     ([turn]#7 \c_colon_str #6/2 ) coordinate (final-RR)
   }
 }

 \exp_last_unbraced:Nf \path \l_tmpa_tl ;
 \exp_last_unbraced:Nf \path \l_tmpb_tl ;

 \tl_set:Nn \l_tzslopeat_cmd_tl
 {
   [ #2 ] (final-LL) -- (final-RR)
 }

 \gdef\TANCurve{#3}\gdef\TANWhere{#4}

 \tzslopeat_final_actions
}

\NewDocumentCommand\tzslopeat_epsilon_process{ m m }
{
 \def\tzslopeatEpsilonOne{#1}
 \def\tzslopeatEpsilonTwo{#2}
}

\NewDocumentCommand\tzslopeat_final_actions{ +G{} O{} D<>{} }
{
 % final action
 \begin{pgfonlayer}{\tzslopelayer}
 \exp_last_unbraced:Nf \draw \l_tzslopeat_cmd_tl node [ #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tzslopeat_cmd_tl ;

}

%%% --- end of \tzslopeat


%%% \tzslope (On)  -- slope line at (x,y)

\bool_new:N \l_tzslope_bbox_bool

%%% \tzslope (main)
\NewDocumentCommand\tzslope
 { t' O{} m r()
   >{ \SplitArgument { 1 } { , } } d()
   m O{0} % +G{} O{} D<>{}
 }
{
 % to resolve discrepancy (due to bounding box), when repeated
 \bool_if:nTF
 {
   \str_if_eq_p:ee { \TANCurve } { #3 } &&
       \str_if_eq_p:ee { \TANWhere } { #4 }
       }
       { \bool_set_true:N \l_tzslope_bbox_bool }
       { \bool_set_false:N \l_tzslope_bbox_bool }

 % for local change of epsilon_1, epsilon_2
 \IfValueT { #5 }
 {
   \tzslope_epsilon_process #5
   \renewcommand\tzslopeepsilonL{\tzslopeEpsilonOne}
   \renewcommand\tzslopeepsilonR{\tzslopeEpsilonTwo}
 }

 % getting ready
 \coordinate (LXcoor) at ($(#4)-(\tzslopeepsilonL,0)$) ;
 \coordinate (RXcoor) at ($(#4)+(\tzslopeepsilonR,0)$) ;

 \bool_if:NTF \l_tzslope_bbox_bool
 {
   \IfNodeDefined{bbxBottom}{}
   {
     \coordinate (bbxTop)    at (current~bounding~box.north) ;
     \coordinate (bbxBottom) at (current~bounding~box.south) ;
   }
 }
 {
   \coordinate (bbxTop)    at (current~bounding~box.north) ;
   \coordinate (bbxBottom) at (current~bounding~box.south) ;
 }

 % find vertical X points
 \path [ name~path = C-vline ] (#4 |- bbxBottom) -- (#4 |- bbxTop) ;
 \path [ name~intersections = { of = #3 ~ and ~ C-vline , name = TANp } ] ;

 \path [ name~path = L-vline ] (LXcoor |- bbxBottom) -- (LXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #3 ~ and ~ L-vline , name = LXcut } ] ;

 \path [ name~path = R-vline ] (RXcoor |- bbxBottom) -- (RXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #3 ~ and ~ R-vline , name = RXcut } ] ;

 % move to tangent point
 \coordinate (tzXproj)
   at ($(LXcut-1)!(TANp-1)!(RXcut-1)$); % projection
 \coordinate (LLpoint)
   at ($(LXcut-1)+(TANp-1)-(tzXproj)$); % move
 \coordinate (RRpoint)
   at ($(RXcut-1)+(TANp-1)-(tzXproj)$); % move

 % determine final extended points
 \tl_set:Nx \l_tmpa_tl
 {
   \IfBooleanTF { #1 }
   {
     (RRpoint) -- (TANp-1) --
     ([turn]-180 \c_colon_str #6/2 ) coordinate (final-LL)
   }
   {
     (RRpoint) -- (TANp-1) --
     ([turn]#7 \c_colon_str #6/2 ) coordinate (final-LL)
   }
 }
 \tl_set:Nx \l_tmpb_tl
 {
   \IfBooleanTF { #1 }
   {
     (LLpoint) -- (TANp-1) --
     ([turn]-180 \c_colon_str #6/2 ) coordinate (final-RR)
   }
   {
     (LLpoint) -- (TANp-1) --
     ([turn]#7 \c_colon_str #6/2 ) coordinate (final-RR)
   }
 }

 \exp_last_unbraced:Nf \path \l_tmpa_tl ;
 \exp_last_unbraced:Nf \path \l_tmpb_tl ;

 \tl_set:Nn \l_tzslope_cmd_tl
 {
   [ #2 ] (final-LL) -- (final-RR)
 }

 \gdef\TANCurve{#3}\gdef\TANWhere{#4}

 \tzslope_final_actions
}

\NewDocumentCommand\tzslope_epsilon_process{ m m }
{
 \def\tzslopeEpsilonOne{#1}
 \def\tzslopeEpsilonTwo{#2}
}

\NewDocumentCommand\tzslope_final_actions{ +G{} O{} D<>{} }
{
 % final action
 \begin{pgfonlayer}{\tzslopelayer}
 \exp_last_unbraced:Nf \draw \l_tzslope_cmd_tl node [ #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tzslope_cmd_tl ;
}

%%% --- end of \tzslope



%%%%% Normal lines
%% No <shift coor>
%% No <shift coor>
%% No <shift coor>

%%% \tznormalat
%% -- normal line at x

\bool_new:N \l_tznormalat_bbox_bool

%%% \tznormalat (main)
\NewDocumentCommand\tznormalat
 { s t' O{} m m
   >{ \SplitArgument { 1 } { , } } d()
   m O{90} % +G{} O{} D<>{}
 }
{
 % to resolve discrepancy (due to bounding box), when repeated
 \bool_if:nTF
 {
   \str_if_eq_p:ee { \TANCurve } { #4 } &&
       \str_if_eq_p:ee { \TANWhere } { #5 }
       }
       { \bool_set_true:N \l_tznormalat_bbox_bool }
       { \bool_set_false:N \l_tznormalat_bbox_bool }

 % for local change of epsilon_1, epsilon_2
 \IfValueT { #6 }
 {
   \tznormalat_epsilon_process #6
   \renewcommand\tznormalepsilonL{\tznormalatEpsilonOne}
   \renewcommand\tznormalepsilonR{\tznormalatEpsilonTwo}
 }

 % getting ready
 \coordinate (LXcoor) at ($(#5,0)-(\tznormalepsilonL,0)$) ;
 \coordinate (RXcoor) at ($(#5,0)+(\tznormalepsilonR,0)$) ;

 \bool_if:NTF \l_tznormalat_bbox_bool
 {
   \IfNodeDefined{bbxBottom}{}
   {
     \coordinate (bbxTop)    at (current~bounding~box.north) ;
     \coordinate (bbxBottom) at (current~bounding~box.south) ;
   }
 }
 {
   \coordinate (bbxTop)    at (current~bounding~box.north) ;
   \coordinate (bbxBottom) at (current~bounding~box.south) ;
 }

 % find vertical X points
 \path [ name~path = C-vline ] (#5,0 |- bbxBottom) -- (#5,0 |- bbxTop) ;
 \path [ name~intersections = { of = #4 ~ and ~ C-vline , name = TANp } ] ;

 \path [ name~path = L-vline ] (LXcoor |- bbxBottom) -- (LXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #4 ~ and ~ L-vline , name = LXcut } ] ;

 \path [ name~path = R-vline ] (RXcoor |- bbxBottom) -- (RXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #4 ~ and ~ R-vline , name = RXcut } ] ;

 % move to tangent point
 \coordinate (tzXproj)
   at ($(LXcut-1)!(TANp-1)!(RXcut-1)$); % projection
 \coordinate (LLpoint)
   at ($(LXcut-1)+(TANp-1)-(tzXproj)$); % move
 \coordinate (RRpoint)
   at ($(RXcut-1)+(TANp-1)-(tzXproj)$); % move

 % determine final extended points
 % from (final-LL)
 \tl_set:Nx \l_tmpa_tl
 {
   \IfBooleanTF { #1 }
   {
     \IfBooleanTF { #2 }
     {
       (RRpoint) -- (TANp-1) --
       ([turn]-90 \c_colon_str #7/2 ) coordinate (final-LL)
     }
     {
       (RRpoint) -- (TANp-1) --
       ([turn]#8 \c_colon_str #7/2 ) coordinate (final-LL)
     }
   }
   {
       (TANp-1) coordinate (final-LL)
   }
 }
 % to (final-RR)
 \tl_set:Nx \l_tmpb_tl
 {
   \IfBooleanTF { #1 }
   { % starred : slope
     \IfBooleanTF { #2 }
     { % opposite direction (swap)
       (LLpoint) -- (TANp-1) --
       ([turn]-90 \c_colon_str #7/2 ) coordinate (final-RR)
     }
     {
       (LLpoint) -- (TANp-1) --
       ([turn]#8 \c_colon_str #7/2 ) coordinate (final-RR)
     }
   }
   {  % standard : normal
     {
       \IfBooleanTF { #2 }
       { % opposite direction (swap)
         (LLpoint) -- (TANp-1) --
         ([turn]-90 \c_colon_str #7/2 ) coordinate (final-RR)
       }
       { % standard normal
         (LLpoint) -- (TANp-1) --
         ([turn]#8 \c_colon_str #7/2 ) coordinate (final-RR)
       }
     }
   }
 }

 \exp_last_unbraced:Nf \path \l_tmpa_tl ;
 \exp_last_unbraced:Nf \path \l_tmpb_tl ;

 \tl_set:Nn \l_tznormalat_cmd_tl
 {
   [ #3 ] (final-LL) -- (final-RR)
 }

 \gdef\TANCurve{#4}\gdef\TANWhere{#5}

 \tznormalat_final_actions
}

\NewDocumentCommand\tznormalat_epsilon_process{ m m }
{
 \def\tznormalatEpsilonOne{#1}
 \def\tznormalatEpsilonTwo{#2}
}

\NewDocumentCommand\tznormalat_final_actions{ +G{} O{} D<>{} }
{
 % final action
 \begin{pgfonlayer}{\tznormallayer}
 \exp_last_unbraced:Nf \draw \l_tznormalat_cmd_tl node [ #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tznormalat_cmd_tl ;
}

%%% --- end of \tznormalat


%%% \tznormal (On)  -- normal line at (x,y)

\bool_new:N \l_tznormal_bbox_bool

%%% \tznormal (main)
\NewDocumentCommand\tznormal
 { s t' O{} m r()
   >{ \SplitArgument { 1 } { , } } d()
   m O{90} % +G{} O{} D<>{}
 }
{
 % to resolve discrepancy (due to bounding box), when repeated
 \bool_if:nTF
 {
   \str_if_eq_p:ee { \TANCurve } { #4 } &&
       \str_if_eq_p:ee { \TANWhere } { #5 }
       }
       { \bool_set_true:N \l_tznormal_bbox_bool }
       { \bool_set_false:N \l_tznormal_bbox_bool }

 % for local change of epsilon_1, epsilon_2
 \IfValueT { #6 }
 {
   \tznormal_epsilon_process #6
   \renewcommand\tznormalepsilonL{\tznormalEpsilonOne}
   \renewcommand\tznormalepsilonR{\tznormalEpsilonTwo}
 }

 % getting ready
 \coordinate (LXcoor) at ($(#5)-(\tznormalepsilonL,0)$) ;
 \coordinate (RXcoor) at ($(#5)+(\tznormalepsilonR,0)$) ;

 \bool_if:NTF \l_tznormal_bbox_bool
 {
   \IfNodeDefined{bbxBottom}{}
   {
     \coordinate (bbxTop)    at (current~bounding~box.north) ;
     \coordinate (bbxBottom) at (current~bounding~box.south) ;
   }
 }
 {
   \coordinate (bbxTop)    at (current~bounding~box.north) ;
   \coordinate (bbxBottom) at (current~bounding~box.south) ;
 }

 % find vertical X points
 \path [ name~path = C-vline ] (#5 |- bbxBottom) -- (#5 |- bbxTop) ;
 \path [ name~intersections = { of = #4 ~ and ~ C-vline , name = TANp } ] ;

 \path [ name~path = L-vline ] (LXcoor |- bbxBottom) -- (LXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #4 ~ and ~ L-vline , name = LXcut } ] ;

 \path [ name~path = R-vline ] (RXcoor |- bbxBottom) -- (RXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #4 ~ and ~ R-vline , name = RXcut } ] ;

 % move to tangent point
 \coordinate (tzXproj)
   at ($(LXcut-1)!(TANp-1)!(RXcut-1)$); % projection
 \coordinate (LLpoint)
   at ($(LXcut-1)+(TANp-1)-(tzXproj)$); % move
 \coordinate (RRpoint)
   at ($(RXcut-1)+(TANp-1)-(tzXproj)$); % move

 % determine final extended points
 % from (final-LL)
 \tl_set:Nx \l_tmpa_tl
 {
   \IfBooleanTF { #1 }
   {
     \IfBooleanTF { #2 }
     {
       (RRpoint) -- (TANp-1) --
       ([turn]-90 \c_colon_str #7/2 ) coordinate (final-LL)
     }
     {
       (RRpoint) -- (TANp-1) --
       ([turn]#8 \c_colon_str #7/2 ) coordinate (final-LL)
     }
   }
   {
       (TANp-1) coordinate (final-LL)
   }
 }
 % to (final-RR)
 \tl_set:Nx \l_tmpb_tl
 {
   \IfBooleanTF { #1 }
   { % starred : slope
     \IfBooleanTF { #2 }
     { % opposite direction (swap)
       (LLpoint) -- (TANp-1) --
       ([turn]-90 \c_colon_str #7/2 ) coordinate (final-RR)
     }
     {
       (LLpoint) -- (TANp-1) --
       ([turn]#8 \c_colon_str #7/2 ) coordinate (final-RR)
     }
   }
   {  % standard : normal
     {
       \IfBooleanTF { #2 }
       { % opposite direction (swap)
         (LLpoint) -- (TANp-1) --
         ([turn]-90 \c_colon_str #7/2 ) coordinate (final-RR)
       }
       { % standard normal
         (LLpoint) -- (TANp-1) --
         ([turn]#8 \c_colon_str #7/2 ) coordinate (final-RR)
       }
     }
   }
 }

 \exp_last_unbraced:Nf \path \l_tmpa_tl ;
 \exp_last_unbraced:Nf \path \l_tmpb_tl ;

 \tl_set:Nn \l_tznormal_cmd_tl
 {
   [ #3 ] (final-LL) -- (final-RR)
 }

 \gdef\TANCurve{#4}\gdef\TANWhere{#5}

 \tznormal_final_actions
}

\NewDocumentCommand\tznormal_epsilon_process{ m m }
{
 \def\tznormalEpsilonOne{#1}
 \def\tznormalEpsilonTwo{#2}
}

\NewDocumentCommand\tznormal_final_actions{ +G{} O{} D<>{} }
{
 % final action
 \begin{pgfonlayer}{\tznormallayer}
 \exp_last_unbraced:Nf \draw \l_tznormal_cmd_tl node [ #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tznormal_cmd_tl ;
}

%%% --- end of \tznormal




%%%%% Tangent lines

%%% \tztangentat -- tangent to a path at x
%%% ref. \settztangentepsilon
%%% [<opt>]<shift coor>"<path name>"{<path>}{<x>}(<epsilon1>,<epsilon2>)[<from>:<to>]{<text>}[<pos,opt>]<code.append>

\bool_new:N \l_tztangentat_bbox_bool

%%% \tztangentat (main)
\use:x{
 \NewDocumentCommand \exp_not:N \tztangentat
 { s O{} d<> D""{} m m
   >{ \SplitArgument { 1 } { , } } d()
   >{ \SplitArgument { 1 } { \tl_to_str:n {:} } } r[] }
 }
{
 \tl_clear:N \l_tztangentat_cmd_tl

 \IfBooleanTF { #1 } % NOT USED!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 % to resolve discrepancy (due to bounding box), when repeated
 \bool_if:nTF
 {
   \str_if_eq_p:ee { \TANCurve } { #5 } &&
       \str_if_eq_p:ee { \TANWhere } { #6 }
       }
       { \bool_set_true:N \l_tztangentat_bbox_bool }
       { \bool_set_false:N \l_tztangentat_bbox_bool }

 % for local change of epsilon_1 and _2
 \IfValueT { #7 }
 {
   \tztangentat_epsilon_process #7
   \renewcommand\tztangentepsilonL{\tztangentatEpsilonOne}
   \renewcommand\tztangentepsilonR{\tztangentatEpsilonTwo}
 }

 \tztangentat_domain_process #8

 % getting ready
 \coordinate (LXcoor)   at ($(#6,0)-(\tztangentepsilonL,0)$) ;
 \coordinate (RXcoor)   at ($(#6,0)+(\tztangentepsilonR,0)$) ;

 \bool_if:NTF \l_tztangentat_bbox_bool
 {
   \IfNodeDefined{bbxBottom}{}
   {
     \coordinate (bbxTop)    at (current~bounding~box.north) ;
     \coordinate (bbxBottom) at (current~bounding~box.south) ;
   }
 }
 {
   \coordinate (bbxTop)    at (current~bounding~box.north) ;
   \coordinate (bbxBottom) at (current~bounding~box.south) ;
 }

 % find vertical X points
 \path [ name~path = C-vline ] (#6,0 |- bbxBottom) -- (#6,0 |- bbxTop) ;
 \path [ name~intersections = { of = #5 ~ and ~ C-vline , name = TANp } ] ;

 \path [ name~path = L-vline ] (LXcoor |- bbxBottom) -- (LXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #5 ~ and ~ L-vline , name = LXcut } ] ;

 \path [ name~path = R-vline ] (RXcoor |- bbxBottom) -- (RXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #5 ~ and ~ R-vline , name = RXcut } ] ;

 % move to tangent point
 \coordinate (tzXproj)
   at ($(LXcut-1)!(TANp-1)!(RXcut-1)$); % projection
 \coordinate (LLpoint)
   at ($(LXcut-1)+(TANp-1)-(tzXproj)$); % move
 \coordinate (RRpoint)
   at ($(RXcut-1)+(TANp-1)-(tzXproj)$); % move

 % determine final extended points
 \tl_set:Nx \l_label_pos_tl
 {
   (RRpoint) -- (TANp-1) --
   ([turn]0 \c_colon_str ~ -\tztangentatFromVal) coordinate (final-LL)
 }
 \tl_set:Nx \l_tmpb_tl
 {
   (LLpoint) -- (TANp-1) --
   ([turn]0 \c_colon_str ~ \tztangentatToVal) coordinate (final-RR)
 }

 \exp_last_unbraced:Nf \path \l_label_pos_tl ;
 \exp_last_unbraced:Nf \path \l_tmpb_tl ;

 \tzgetxyval(LLpoint){\tzTANLLX}{\tzTANLLY}
 \tzgetxyval(RRpoint){\tzTANRRX}{\tzTANRRY}

 \edef\tzTANSlope{(\tzTANRRY-\tzTANLLY)/(\tzTANRRX-\tzTANLLX)}
 \def\tztangentatLFn{\tzTANSlope*(\x-\tzTANLLX)+\tzTANLLY}

 \IfValueTF { #3 }
 {
   \tl_put_right:Nn \l_tztangentat_cmd_tl
   {
     [ name~path = #4 ,
       shift = { (#3) } ,
   }
 }
 {
   \tl_put_right:Nn \l_tztangentat_cmd_tl
   {
     [ name~path = #4 ,
   }
 }

 \tl_put_right:Nx \l_tztangentat_cmd_tl
   {
       domain = \tztangentatFromVal \c_colon_str \tztangentatToVal ,
   }

 \tl_put_right:Nn \l_tztangentat_cmd_tl
   {
       #2 ]
     plot ( \x , { \tztangentatLFn } ) % \x should not be expanded
   }

 \gdef\TANCurve{#5}\gdef\TANWhere{#6}

%  \tztangentat_sub_fn:n
 \tztangentat_final_actions
}

\NewDocumentCommand\tztangentat_epsilon_process{ m m }
{
 \def\tztangentatEpsilonOne{#1}
 \def\tztangentatEpsilonTwo{#2}
}

\NewDocumentCommand\tztangentat_domain_process{ m m }
{
 \def\tztangentatFromVal{#1}
 \def\tztangentatToVal{#2}
}

%\cs_new:Npn \tztangentat_sub_fn:n
%{
%  \tztangentat_final_actions
%}

\NewDocumentCommand\tztangentat_final_actions { +G{} O{} D<>{} }
{
 \begin{pgfonlayer}{\tztangentlayer}
 \exp_last_unbraced:Nf \draw \l_tztangentat_cmd_tl
   node [ black , above~right , #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tztangentat_cmd_tl ;
}

%%% --- end of \tztangentat


%%% \tztangent (On) -- tangent to a path at (x,y)
%%% [<opt>]<shift coor>"<path name>"{<path>}(<coor>)(<epsilon1>,<epsilon2>)[<from>:<to>]{<text>}[<pos,opt>]<code.append>

\bool_new:N \l_tztangent_bbox_bool

%%% \tztangent (main)
\use:x{
 \NewDocumentCommand \exp_not:N \tztangent
 { s O{} d<> D""{} m r()
   >{ \SplitArgument { 1 } { , } } d()
   >{ \SplitArgument { 1 } { \tl_to_str:n {:} } } r[] }
 }
{
 \tl_clear:N \l_tztangent_cmd_tl

 \IfBooleanTF { #1 } % NOT USED!
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 % to resolve discrepancy (due to bounding box), when repeated
 \bool_if:nTF
 {
   \str_if_eq_p:ee { \TANCurve } { #5 } &&
       \str_if_eq_p:ee { \TANWhere } { #6 }
       }
       { \bool_set_true:N \l_tztangent_bbox_bool }
       { \bool_set_false:N \l_tztangent_bbox_bool }

 % for local change of epsilon_1 and _2
 \IfValueT { #7 }
 {
   \tztangent_epsilon_process #7
   \renewcommand\tztangentepsilonL{\tztangentEpsilonOne}
   \renewcommand\tztangentepsilonR{\tztangentEpsilonTwo}
 }

 \tztangent_domain_process #8

 % getting ready
 \coordinate (LXcoor)   at ($(#6)-(\tztangentepsilonL,0)$) ;
 \coordinate (RXcoor)   at ($(#6)+(\tztangentepsilonR,0)$) ;

 \bool_if:NTF \l_tztangent_bbox_bool
 {
   \IfNodeDefined{bbxBottom}{}
   {
     \coordinate (bbxTop)    at (current~bounding~box.north) ;
     \coordinate (bbxBottom) at (current~bounding~box.south) ;
   }
 }
 {
   \coordinate (bbxTop)    at (current~bounding~box.north) ;
   \coordinate (bbxBottom) at (current~bounding~box.south) ;
 }

 % find vertical X points
 \path [ name~path = C-vline ] (#6 |- bbxBottom) -- (#6 |- bbxTop) ;
 \path [ name~intersections = { of = #5 ~ and ~ C-vline , name = TANp } ] ;

 \path [ name~path = L-vline ] (LXcoor |- bbxBottom) -- (LXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #5 ~ and ~ L-vline , name = LXcut } ] ;

 \path [ name~path = R-vline ] (RXcoor |- bbxBottom) -- (RXcoor |- bbxTop) ;
 \path [ name~intersections = { of = #5 ~ and ~ R-vline , name = RXcut } ] ;

 % move to tangent point
 \coordinate (tzXproj)
   at ($(LXcut-1)!(TANp-1)!(RXcut-1)$); % projection
 \coordinate (LLpoint)
   at ($(LXcut-1)+(TANp-1)-(tzXproj)$); % move
 \coordinate (RRpoint)
   at ($(RXcut-1)+(TANp-1)-(tzXproj)$); % move

 % determine final extended points
 \tl_set:Nx \l_label_pos_tl
 { (RRpoint) -- (TANp-1) --
   ([turn]0 \c_colon_str ~ -\tztangentFromVal) coordinate (final-LL) }
 \tl_set:Nx \l_tmpb_tl
 { (LLpoint) -- (TANp-1) --
   ([turn]0 \c_colon_str ~ \tztangentToVal) coordinate (final-RR) }

 \exp_last_unbraced:Nf \path \l_label_pos_tl ;
 \exp_last_unbraced:Nf \path \l_tmpb_tl ;

 \tzgetxyval(LLpoint){\tzTANLLX}{\tzTANLLY}
 \tzgetxyval(RRpoint){\tzTANRRX}{\tzTANRRY}

 \edef\tzTANSlope{(\tzTANRRY-\tzTANLLY)/(\tzTANRRX-\tzTANLLX)}
 \def\tztangentLFn{\tzTANSlope*(\x-\tzTANLLX)+\tzTANLLY}

 \IfValueTF { #3 }
 {
   \tl_put_right:Nn \l_tztangent_cmd_tl
   {
     [ name~path = #4 ,
       shift = { (#3) } ,
   }
 }
 {
   \tl_put_right:Nn \l_tztangent_cmd_tl
   {
     [ name~path = #4 ,
   }
 }

 \tl_put_right:Nx \l_tztangent_cmd_tl
   {
       domain = \tztangentFromVal \c_colon_str \tztangentToVal ,
   }

 \tl_put_right:Nn \l_tztangent_cmd_tl
   {
       #2 ]
     plot ( \x , { \tztangentLFn } ) % \x should not be expanded
   }

 \gdef\TANCurve{#5}\gdef\TANWhere{#6}

%  \tztangent_sub_fn:n
 \tztangent_final_actions
}

\NewDocumentCommand\tztangent_epsilon_process{ m m }
{
 \def\tztangentEpsilonOne{#1}
 \def\tztangentEpsilonTwo{#2}
}

\NewDocumentCommand\tztangent_domain_process{ m m }
{
 \def\tztangentFromVal{#1}
 \def\tztangentToVal{#2}
}

%\cs_new:Npn \tztangent_sub_fn:n
%{
%  \tztangent_final_actions
%}

\NewDocumentCommand\tztangent_final_actions { +G{} O{} D<>{} }
{
 \begin{pgfonlayer}{\tztangentlayer}
 \exp_last_unbraced:Nf \draw \l_tztangent_cmd_tl
   node [ black , above~right , #2 ] { #1 } #3 ;
 \end{pgfonlayer}
 % to resolve TikZ issue: unknown path name with layer group
 \exp_last_unbraced:Nf \path \l_tztangent_cmd_tl ;
}

%%% --- end of \tztangent




%%%%% \tzbrace

%%% \tzbrace'[<opt>]{<raise>}[<brace opt>]
%%%          <shift coor>(<coor>)(<coor>){<text>}[<pos,opt>]
\NewDocumentCommand\tzbrace{ t' O{} G{5pt} O{} d<> r() r() +G{} O{} }
{
 \IfBooleanTF { #1 }
 {
   \draw [ decorate , decoration =
           { calligraphic~brace , mirror ,
             amplitude = 5pt, raise = #3 , #4 } , #2
         ]
 }
 {
   \draw [ decorate , decoration =
           { calligraphic~brace ,
             amplitude = 5pt, raise = #3 , #4 } , #2
         ]
 }
 \IfValueTF { #5 }
 {
   ([shift={(#5)}]#6) to node [ midway , #9 ] { #8 }
   ([shift={(#5)}]#7) ;
 }
 {
   (#6) to node [ midway , #9 ] { #8 } (#7) ;
 }
}

%%% -- end of \tzbrace


%%%(ADDED)
%%% \tzsnake

\bool_new:N \l_tzsnake_shift_coor_bool

%%% \tzsnake (main)
\NewDocumentCommand\tzsnake{ s t+ o G{5pt} O{} d<> }
{
 \tl_clear:N \l_tzsnake_cmd_tl

 \IfBooleanTF { #1 } % (*) or not  (NOT USED!)
 { \bool_set_true:N \l_tmpa_bool }
 { \bool_set_false:N \l_tmpa_bool }

 \IfBooleanTF { #2 } % (+) or not
 { \bool_set_true:N \l_tmpb_bool }
 { \bool_set_false:N \l_tmpb_bool }

 \IfValueTF { #3 }
 { \tl_set:Nn \l_tzsnake_opt_tl { #3 } }
 { \tl_clear:N \l_tzsnake_opt_tl }

 \tl_set:Nn \l_tzsnake_segment_length_tl { #4 }

 \tl_set:Nn \l_tzsnake_snake_opt_tl { #5 }

 \IfValueTF { #6 }
 {
   \tl_set:Nn \l_tzsnake_shift_coor_tl { #6 }
   \bool_set_true:N \l_tzsnake_shift_coor_bool
 }
 {
   \tl_clear:N \l_tzsnake_shift_coor_tl
   \bool_set_false:N \l_tzsnake_shift_coor_bool
 }

 \tzsnake_check_token:n
}

\cs_new:Npn \tzsnake_check_token:n #1
{
 \str_if_eq:nnT { #1 } { ( }
   { \tzsnake_sub_fn ( }
%  \tzsnake_stop_action
}

\NewDocumentCommand\tzsnake_sub_fn{ r() +G{} O{} r() +G{} O{} D<>{} }
{

 \bool_if:NTF \l_tzsnake_shift_coor_bool
 {% if shift
   \tl_put_right:Nx \l_tzsnake_cmd_tl
   { ([ shift = { (\l_tzsnake_shift_coor_tl) } ]#1) }
 }
 { \tl_put_right:Nn \l_tzsnake_cmd_tl { (#1) } }

 \tl_put_right:Nn \l_tzsnake_cmd_tl
   { to ~node [ #3 ] { #2 } }

 \bool_if:NTF \l_tmpb_bool
 {% if ++
   \tl_put_right:Nn \l_tzsnake_cmd_tl { ++ (#4) }
 }
 {% no ++
   \bool_if:NTF \l_tzsnake_shift_coor_bool
   {% if shift
     \tl_put_right:Nx \l_tzsnake_cmd_tl
     { ([ shift = { (\l_tzsnake_shift_coor_tl) } ]#4) }
   }
   { \tl_put_right:Nn \l_tzsnake_cmd_tl { (#4) } }
 }

 \tl_put_right:Nn \l_tzsnake_cmd_tl
   { node [ #6 ] { #5 } }

 % final action
 \tl_put_left:No \l_tzsnake_cmd_tl
 {
   \l_tzsnake_opt_tl ]    % expand `once' needed
 }

 \tl_put_left:Nx \l_tzsnake_cmd_tl
   {
     [ decorate ,
       decoration =
         { snake ,
           pre~length = 5pt , post~length = 5pt ,
           amplitude = 2.5pt ,
           segment~length = \l_tzsnake_segment_length_tl ,
           \l_tzsnake_snake_opt_tl
         } ,
   }

 \exp_last_unbraced:Nf \draw \l_tzsnake_cmd_tl #7 ;
}

%%% --- end of \tzsnake


%%%(ADDED)
%%% \tzspy

\NewDocumentCommand\tzspy{ s O{} G{2cm} O{5} r() r() O{} D<>{} }
{
 \IfBooleanTF { #1 } {}{} % (NOT USED!!!)
 \spy [ circle , size = #3 , magnification = #4 , #2 ]
      on (#5) in~node at (#6) [ #7 ] #8 ;
}

%%% --- end of \tzspy



%%%%% Arrows (copy from istgame.sty and modified)


%%%%% middle arrows

%%% mid arrow styles
%% \tz@default... used

%% defaults
\def\tz@default@midarrow@pos   { .5 } % istgame: .55
\def\tz@midarrow@pos           { \tz@default@midarrow@pos }
\def\tz@default@midarrow@opt   {    } % istgame: black
\def\tz@midarrow@opt           { \tz@default@midarrow@opt }
\def\tz@default@midarrow@shape { >  }
\def\tz@midarrow@shape         { \tz@default@midarrow@shape }
\newcommand*\tzmidarrowpos     { \tz@midarrow@pos }
\newcommand*\tzmidarrowopt     { \tz@midarrow@opt }
\newcommand*\tzmidarrowshape   { \tz@midarrow@shape }


%% \settzmidarrow
%% to toss values to arrow tip styles
\NewDocumentCommand \settzmidarrow
{
   D<>{ \tz@default@midarrow@pos }
   G{ \tz@default@midarrow@shape }
   O{ \tz@default@midarrow@opt }
}
{
   \renewcommand*\tz@midarrow@pos   { #1 }
   \renewcommand*\tz@midarrow@shape { #2 }
   \renewcommand*\tzmidarrowopt
     { - , thin , solid , shorten~> = 0 , shorten~< = 0 , bend~right = 0 , #3 }
}

%% initial set for defaults
\AtBeginDocument{\settzmidarrow}

%% -->-- : position controllable by \settzmidarrow<pos>
\tikzset
{ -->-- /.style =
 {
   decoration =
   {
     markings ,
     mark = at~position~ #1 ~with~
            { \exp_last_unbraced:NNV \arrow [ \tzmidarrowopt ] { \tzmidarrowshape } }
   } ,
   postaction = {decorate}
 } ,
 -->-- /.default = \tz@midarrow@pos
}


\tikzset
{ --o-- /.style =
 {
   decoration =
   {
     markings ,
     mark = at~position~ #1 ~with~
            {
%               \exp_last_unbraced:NNo \arrow [ \tzmidarrowopt ] { o }
               \exp_last_unbraced:NNf
                 \draw [ \tzmidarrowopt ] (0,0) circle (1.2pt) ;
            }
   } ,
   postaction = {decorate}
 } ,
 --o-- /.default = .5 % istgame: .55
}

\tikzset
{ --x-- /.style =
 {
   decoration =
   {
     markings ,
     mark
     = at~position~ #1 ~with~
       {  % use the option tzextend{2pt}{2pt} to change lenghts
         \exp_last_unbraced:NNo
           \draw [ \tzmidarrowopt ] (2pt,2pt) to (-2pt,-2pt) ;
         \exp_last_unbraced:NNo
           \draw [ \tzmidarrowopt ] (-2pt,2pt) to (2pt,-2pt) ;
       }
   } ,
   postaction = {decorate}
 } ,
 --x-- /.default = .5
}

\tikzset
{ --/-- /.style =
 {
   decoration =
   {
     markings ,
     mark
     = at~position~ #1 ~with~
       {  % use the option tzextend{2pt}{2pt} to change lenghts
         \exp_last_unbraced:NNo
           \draw [ \tzmidarrowopt ] (2pt,2pt) to (-2pt,-2pt) ;
%          \exp_last_unbraced:NNo
%            \draw [ \tzmidarrowopt ] (-2pt,2pt) to (2pt,-2pt) ;
       }
   } ,
   postaction = {decorate}
 } ,
 --/-- /.default = .5
}


%=====================================================
%=====================================================
\ExplSyntaxOff
%=====================================================
%=====================================================


%%% mixed NE

% tzEu
\NewDocumentCommand\TzEu{D(){LFname}O{}mmD<>{\tmpB}O{right}G{}}
{
\def\tmpEu{(#3-#4)*\x+#4}
\def\tmpB{#3} %???
\draw [name path=#1,#2] (0,#4) node [left] {#4} plot [domain=0:1] (\x,{\tmpEu}) node [right] {#5} node [#6] {#7};
}

% tzEu
%\NewDocumentCommand\TzEu{D(){LFname}O{}mmD<>{\tmpB}O{right}G{}}
\NewDocumentCommand\TzEU { O{} D""{} m m D[.{0} D.]{1} D<>{\tmpB} O{right} G{} }
{
\def\tmpEU{(#3-#4)*\x+#4}
\def\tmpB{#3} %???
%\draw [name path=#1,#2] (0,#4) node [left] {#4} plot [domain=0:1] (\x,{\tmpEu}) node [right] {#5} node [#6] {#7};
\Tzfn [#1]"#2"{\tmpEU}[{#5}..{#6}]
\path (0,#4) node [left] {#4} plot [domain=0:1] (\x,{\tmpEU}) node [right] {#7} node [#8] {#9};
}


\endinput