%% 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
