%%%==============================================================================
%% Copyright 2024-present by Alceu Frigeri
%%
%% This work may be distributed and/or modified under the conditions of
%%
%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
%%   version 1.3c (or later), and/or
%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
%%   version 3 (or later)
%%
%% This work has the LPPL maintenance status *maintained*.
%%
%% The Current Maintainer of this work is Alceu Frigeri
%%
%% This is version {1.3b} {2025/11/10}
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/tikzdotncross
%%
%%%==============================================================================
%% WARNING: These are personal packs/tests
%%          They might and probably will change at will as needed
%% 
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2022/06/01]

\ProvidesExplPackage
    {tikzdotncross}
    {2025/11/10}
    {1.3b}
    {Marking coordinates and crossing paths}

%%%%%%%
%%%
%%% Just an attempt of having my package's info in a regular way
%%% \Pkginfograb_set:nn {<pkg-name>} { props} for each and all.
%%%
%%%%%%%
\RequirePackage{pkginfograb}
\pkginfograb_set:nn { tikzdotncross }
  {
     name        = {tikzdotncross} ,
     prefix      = {dotncross} ,
     date        = {2025/11/10},
     version     = {1.3b} ,
     description = {Marking~ coordinates~ and~ crossing~ paths}
  }
%%%%%%%
%%% End of cut-n-paste
%%%%%%%

%%%
%%% why that here? well, the token list's commands will be used outside expl3 'domain'
%%%
\makeatletter

\keys_define:nn { tikzdotncross }
  {
    pin size .tl_set:N          = \l__dotncross_pinsep_tl ,
    pin size .value_required:n  = true ,
    pin size .initial:n         = 1.2 ,
    pin size .usage:n           = general ,

    pin ang .tl_set:N          = \l__dotncross_pinang_tl ,
    pin ang .value_required:n  = true ,
    pin ang .initial:n         = 45 ,
    pin ang .usage:n           = general ,

    pin color .tl_set:N          = \l__dotncross_pincolor_tl ,
    pin color .value_required:n  = true ,
    pin color .initial:n         = blue ,
    pin color .usage:n           = general ,

    pin length .tl_set:N          = \l__dotncross_pindistance_tl ,
    pin length .value_required:n  = true ,
    pin length .initial:n         = 4 ,
    pin length .usage:n           = general ,

    coord color .tl_set:N          = \l__dotncross_coordcolor_tl ,
    coord color .value_required:n  = true ,
    coord color .initial:n         = red ,
    coord color .usage:n           = general ,
  }

\ProcessKeyOptions [ tikzdotncross ]

\NewDocumentCommand{\setpindefaults}{m} {
  \keys_set:nn {tikzdotncross}{#1}
}


  %%%%%%%%%%%%%%%%%%%
  %%%%
  %%%% some handy/auxiliary macros to define coordinate/node pairs (and selectively 'pin' them)
  %%%% based on the idea from Redaelli et al. (CircuiTiKz)
  %%%%
  %%%% differences: variable number of paramenters (see below) and it always also adds an empty node n<coord>
  %%%%
  %%%%%%%%%%%%%%%%%%%

\keys_define:nn { tikzdotncross / show coords}
  {
    on .code:n              = \__dotncross_showcoords: ,
    on .value_forbidden:n   = true ,
    
    off .code:n             = \__dotncross_hidecoords: ,
    off .value_forbidden:n  = true ,

    true .code:n              = \__dotncross_showcoords: ,
    true .value_forbidden:n   = true ,
    
    false .code:n             = \__dotncross_hidecoords: ,
    false .value_forbidden:n  = true ,
  }

\cs_new:Npn \__dotncross_hidecoords:
  {
    \cs_set_eq:NN \ncoord    \__dotncross_coordnode:w 
    \cs_set_eq:NN \dotcoord  \__dotncross_dotcoordnode:w 
    \cs_set_eq:NN \odotcoord \__dotncross_odotcoordnode:w
  }

\cs_new:Npn \__dotncross_showcoords:
  {
    \cs_set_eq:NN \ncoord    \__dotncross_coordpin:w 
    \cs_set_eq:NN \dotcoord  \__dotncross_dotcoordpin:w 
    \cs_set_eq:NN \odotcoord \__dotncross_odotcoordpin:w
  }

\NewDocumentCommand{\showcoords}{m} {
  \keys_set:nn {tikzdotncross / show coords}{#1}
}

\cs_new_eq:NN \showcoordsfalse \__dotncross_hidecoords:
\cs_new_eq:NN \showcoordstrue  \__dotncross_showcoords:


\cs_new:Npn \__dotncross_coordpin:w (#1)
  {
    \pincoord(#1,\l__dotncross_coordcolor_tl,\l__dotncross_pinang_tl)
  }
\cs_new:Npn \__dotncross_coordnode:w (#1)
  {
    coordinate(#1)  node[minimum ~ size=\l__dotncross_pinsep_tl pt,inner ~ sep=\l__dotncross_pinsep_tl pt](n#1){}
  }

\cs_new:Npn \__dotncross_dotcoordpin:w (#1)
  {
    \dotpincoord(#1,\l__dotncross_coordcolor_tl,\l__dotncross_pinang_tl)
  }
\cs_new:Npn \__dotncross_dotcoordnode:w (#1)
  {
    coordinate(#1)  node[circle,minimum ~ size=\l__dotncross_pinsep_tl pt,inner ~ sep=\l__dotncross_pinsep_tl pt,fill](n#1){}
  }

\cs_new:Npn \__dotncross_odotcoordpin:w (#1)
  {
    \odotpincoord(#1,\l__dotncross_coordcolor_tl,\l__dotncross_pinang_tl)
  }
\cs_new:Npn \__dotncross_odotcoordnode:w (#1)
  {
    coordinate(#1)  node[circle,minimum ~ size=\l__dotncross_pinsep_tl pt,inner ~ sep=\l__dotncross_pinsep_tl pt,fill=white,draw](n#1){}
  }


    %%%%
    %%
    %%  And some TeX to have a (expandable) variable number of parameters
    %%  \pincoord can be used as
    %%  \pincoord(coord-name) That's case D
    %%  \pincoord(coord-name,color) That's case C
    %%  \pincoord(coord-name,color,angle) That's case B
    %%  \pincoord(coord-name,color,angle,lenght) That's case A
    %%
    %%%%    
    %%
    %% new/revised code
    %% Note that: \dotncross@@pincoord expects 6 parameters !
    %% That's why __dotncross_pincase:nn expects 2 ! 
    %% The one that follows will be this last parameter
    %%
    %%%%    
\scan_new:N \s__dotncross

\cs_new:Npn \__dotncross_pincase:nn #1
  {
    \__dotncross_pincase:w 
      #1 ,,,, \__dotncross_pincaseA:nnnnn \__dotncross_pincaseB:nnnnn \__dotncross_pincaseC:nnnnn \__dotncross_pincaseD:nnnnn  \s__dotncross 
  }

    %%%%    
    %%
    %% Minimizing parameters juggling.
    %% Note that, at first, the parameters order is reverted !
    %% That Way:
    %% pincaseA: can absorb them all 'directly'
    %% pincaseB: just discards the first one   (almost \use_none:n) and absorbs the 'rest'
    %% pincaseC: just discards the first two   (almost \use_none:nn) and absorbs the 'rest'
    %% pincaseD: just discards the first three (almost \use_none:nnn) and absorbs the 'rest'
    %%
    %%%%    

\cs_new:Npn \__dotncross_pincase:w  #1,#2,#3,#4,#5#6#7#8#9 \s__dotncross 
  {
    #8  {#4}{#3}{#2}{#1}
  }
\cs_new:Npn \__dotncross_pincaseA:nnnnn
  {
    \dotncross@@pincoord \l__dotncross_pinsep_tl
  }
\cs_new:Npn \__dotncross_pincaseB:nnnnn    #1
  {
    \dotncross@@pincoord \l__dotncross_pinsep_tl \l__dotncross_pindistance_tl
  }
\cs_new:Npn \__dotncross_pincaseC:nnnnn    #1#2
  {
    \dotncross@@pincoord \l__dotncross_pinsep_tl \l__dotncross_pindistance_tl {-\l__dotncross_pinang_tl}
  }
\cs_new:Npn \__dotncross_pincaseD:nnnnn    #1#2#3
  {
    \dotncross@@pincoord \l__dotncross_pinsep_tl \l__dotncross_pindistance_tl {-\l__dotncross_pinang_tl} {\l__dotncross_pincolor_tl} 
  }


\cs_new:Npn \pincoord (#1)
  {
    \__dotncross_pincase:nn {#1}{}
  }
\cs_new:Npn \dotpincoord (#1)
  {
    \__dotncross_pincase:nn {#1}{circle,fill,}
  }
\cs_new:Npn \odotpincoord (#1)
  {
    \__dotncross_pincase:nn {#1}{circle,fill=white,draw,}
  }

\showcoordsfalse        

%%
%%  Original/Old TeX code
%%
%%  %%%%%%%%%%%%%%%%%%%
%%  %%%%
%%  %%%% some handy/auxiliary macros to define coordinate/node pairs (and selectively 'pin' them)
%%  %%%% based on the idea from Redaelli et al. (CircuiTiKz)
%%  %%%%
%%  %%%% differences: variable number of paramenters (see below) and it always also adds an empty node n<coord>
%%  %%%%
%%  %%%%%%%%%%%%%%%%%%%
%%\newcommand\showcoordsfalse{\let\ncoord=\dotncross@@coordnode \let\dotcoord=\dotncross@@dotcoordnode \let\odotcoord=\dotncross@@odotcoordnode}
%%\newcommand\showcoordstrue{\let\ncoord=\dotncross@@coordpin \let\dotcoord=\dotncross@@dotcoordpin \let\odotcoord=\dotncross@@odotcoordpin}
%%
%%\def\dotncross@@coordpin(#1){\pincoord(#1,\dotncross@@coordcolor,\dotncross@@pinang)}
%%\def\dotncross@@coordnode(#1){coordinate(#1)  node[minimum size=\dotncross@@pinsep pt,inner sep=\dotncross@@pinsep pt](n#1){}}
%%
%%\def\dotncross@@dotcoordpin(#1){\dotpincoord(#1,\dotncross@@coordcolor,\dotncross@@pinang)}
%%\def\dotncross@@dotcoordnode(#1){coordinate(#1)  node[circle,minimum size=\dotncross@@pinsep pt,inner sep=\dotncross@@pinsep pt,fill](n#1){}}
%%
%%\def\dotncross@@odotcoordpin(#1){\odotpincoord(#1,\dotncross@@coordcolor,\dotncross@@pinang)}
%%\def\dotncross@@odotcoordnode(#1){coordinate(#1)  node[circle,minimum size=\dotncross@@pinsep pt,inner sep=\dotncross@@pinsep pt,fill=white,draw](n#1){}}
%%
%%    %%%%
%%    %%
%%    %%  And some TeX to have a (expandable) variable number of parameters
%%    %%  \pincoord can be used as
%%    %%  \pincoord(coord-name) That's case D
%%    %%  \pincoord(coord-name,color) That's case C
%%    %%  \pincoord(coord-name,color,angle) That's case B
%%    %%  \pincoord(coord-name,color,angle,lenght) That's case A
%%    %%
%%    %%%%    
%%\def\dotncross@@pincasew#1#2{\dotncross@@pincase#1,,,,\dotncross@@pincaseA\dotncross@@pincaseB\dotncross@@pincaseC\dotncross@@pincaseD;#2:}
%%\def\dotncross@@pincase#1,#2,#3,#4,#5#6#7#8#9:{#8:#1:#2:#3:#4:#9:}
%%\def\dotncross@@pincaseA:#1:#2:#3:#4:#5;#6:{\dotncross@@pincoord{#1}{#2}{#3}{#4}{#6}}
%%\def\dotncross@@pincaseB:#1:#2:#3:#4:#5;#6:{\dotncross@@pincoord{#1}{#2}{#3}{\dotncross@@pindistance}{#6}}
%%\def\dotncross@@pincaseC:#1:#2:#3:#4:#5;#6:{\dotncross@@pincoord{#1}{#2}{-\dotncross@@pinang}{\dotncross@@pindistance}{#6}}
%%\def\dotncross@@pincaseD:#1:#2:#3:#4:#5;#6:{\dotncross@@pincoord{#1}{\dotncross@@pincolor}{-\dotncross@@pinang}{\dotncross@@pindistance}{#6}}
%
%%\def\pincoord(#1){\dotncross@@pincasew{#1}{}}
%%\def\dotpincoord(#1){\dotncross@@pincasew{#1}{circle,fill,}}
%%\def\odotpincoord(#1){\dotncross@@pincasew{#1}{circle,fill=white,draw,}}
%
%%\newcommand\dotncross@@pincoord[5]{%
%%  coordinate(#1) node[#5minimum size=\dotncross@@pinsep pt,inner sep=\dotncross@@pinsep pt](n#1){}
%%  node[circle, #2,  inner sep=\dotncross@@pinsep pt, outer sep=0pt, radius=1pt, fill=#2!20!white, fill opacity=0.2, draw opacity=0.4, draw,
%%    pin={[#2, overlay, inner sep=0pt, outer sep=1pt, font=\tiny, pin distance=#4pt,
%%    pin edge={#2, overlay}]#3:#1}]{}%
%%}


\ExplSyntaxOff

\usetikzlibrary{math,intersections}
\RequirePackage{etoolbox}

    %%
    %% There is no easy and clean way 
    %% to convert this all to expl3 (for instance underscore, under expl3 code régime, is a letter)
    %% spaces (pgf/tikz) and then ':' (which is an active character under tikz but a letter for expl3) 
    %% ... and still being expandable
    %%

  %%%%%%%%%%%%%%%%%%%
  %%%
  %%% This will 'calculate' the intersection between a line (defined by the coordinates (#3) and (#4) and the path named #5
  %%% at each intersection a coordinate named (#2-i) and a node (n#2-i) will be defined (i stands for a counter from 1 up to the number of crossings)
  %%% A macro named <#1T> will have the number of crossings found.
  %%%
  %%% At each intersection a semi-circle will be drawn.
  %%%
  %%% the first parameter #1, star, flips the semi-circle.
  %%%
  %%%%%%%%%%%%%%%%%%%
\NewDocumentCommand{\pathcross}{sO{cross}mmmO{7pt}}{%
   \IfBooleanTF{#1}{\def\dotncross@path@@sign{-}}{\def\dotncross@path@@sign{}}    
   \path[name path=#2 self] (#3) -- (#4);
   \draw[name intersections={of={#5} and {#2 self},name=#2,total=\CrossTotal,sort by={#2 self}}] 
      \pgfextra{\csxdef{#2T}{\CrossTotal}}
      \foreach \aux in {1,...,\csuse{#2T}}{(#2-\aux) node[minimum size=#6-\pgflinewidth,inner sep=0pt](n#2-\aux){}};  
  \tikzmath{%
    coordinate \Ctmp; real \dtmp; int \idx;
    \Ctmp{from} = (#3);
    \Ctmp{to} = (#4);
    \dtmp{x} = \Ctmpx{to} - \Ctmpx{from};
    \dtmp{y} = \Ctmpy{to} - \Ctmpy{from};
    \dtmp{ang} = atan2(\dtmp{y},\dtmp{x});
    \Ctmp{1st} = (n#2-1);
    \Ctmp{last} = (n#2-\csuse{#2T});
    \idx{1st} = 1;
    \idx{last} = \csuse{#2T};
    if \Ctmpx{1st} == \Ctmpx{from} then {
      if \Ctmpy{1st} == \Ctmpy{from} then {
        \idx{1st} = 2; 
      };
    };
    if \Ctmpx{last} == \Ctmpx{to} then {
      if \Ctmpy{last} == \Ctmpy{to} then {
        \idx{last} = \idx{last}-1;
      };
    };
  }
  \ifnum\idx{last}<\idx{1st}
    \draw (#3) -- (#4);
  \else
    \draw[line width=1.8\pgflinewidth,white,rotate=\dtmp{ang}]
      \foreach \aux in {\idx{1st},...,\idx{last}}{(#2-\aux) +(-#6/2,0) arc[start angle=\dotncross@path@@sign180,end angle=0,radius=#6/2]};
    \draw[rotate=\dtmp{ang},line cap=round]
      \foreach \aux in {\idx{1st},...,\idx{last}}{(#2-\aux) +(-#6/2,0) arc[start angle=\dotncross@path@@sign180,end angle=0,radius=#6/2]};
  
    \gdef\dotncross@path@@tmpA{#3}
    \gdef\dotncross@path@@ListA{}
    \foreach \x in {\idx{1st},...,\idx{last}} {\xappto{\dotncross@path@@ListA}{\dotncross@path@@tmpA/n#2-\x,}\xdef\dotncross@path@@tmpA{n#2-\x}}
    \xappto{\dotncross@path@@ListA}{n#2-\idx{last}/#4}
    \foreach \xa/\xb in \dotncross@path@@ListA {\draw[line cap=round] (\xa) -- (\xb);}
  \fi
 }


%%%%%%%
%%%%%%%
%%%
%%% Remember: The ':'  is a pgf/tikz active character
%%%
%%%%%%%
%%%%%%%

%
% Old parameter sequence... note that, between them, #2..#5 are reverted
%
%\newcommand\dotncross@@pincoord[6]{%
%  coordinate(#2) node[#6minimum size=#1 pt,inner sep=#1 pt](n#2){}
%  node[circle, #3,  inner sep=#1 pt, outer sep=0pt, radius=1pt, fill=#3!20!white, fill opacity=0.2, draw opacity=0.4, draw,
%    pin={[#3, overlay, inner sep=0pt, outer sep=1pt, font=\tiny, pin distance=#5pt,
%    pin edge={#3, overlay}]#4:#2}]{}%
%}


\newcommand\dotncross@@pincoord[6]{%
  coordinate(#5) node[#6minimum size=#1 pt,inner sep=#1 pt](n#5){}
  node[circle, #4,  inner sep=#1 pt, outer sep=0pt, radius=1pt, fill=#4!20!white, fill opacity=0.2, draw opacity=0.4, draw,
    pin={[#4, overlay, inner sep=0pt, outer sep=1pt, font=\tiny, pin distance=#2pt,
    pin edge={#4, overlay}]#3:#5}]{}%
}


