%%%==============================================================================
%% 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.1} {2024/01/11}
%%
%% 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}
    {2024/01/11}
    {1.1}
    {Marking coordinates and crossing paths}

%%%%%%%
%%%
%%% Just an attempt of having my packages info in a regular way
%%% Idea being: { <pck-name> / pkg info } for each and all.
%%%
%%%%%%%
\keys_define:nn { tikzdotncross / pkg info}
  {
     name        .code:n = {tikzdotncross} ,
     prefix      .code:n = {tikzdotncross} ,
     date        .code:n = {2024/01/11},
     version     .code:n = {1.1} ,
     description .code:n = {Marking~ coordinates~ and~ crossing~ paths}
  }
\cs_if_exist:NF \PkgInfo 
  {
    \NewDocumentCommand \PkgInfo {mm} { \keys_set:nn {#1 / pkg info}{#2} } 
    \NewDocumentCommand \PkgDescription {m} 
      { \noindent Package~ \textbf{\PkgInfo{#1}{name}}~Version:~\PkgInfo{#1}{version}~ -~ \PkgInfo{#1}{date}\par \emph{\PkgInfo{#1}{description}}~\par } 
  }  
%%%%%%%
%%% End of cut-n-paste
%%%%%%%

\ExplSyntaxOff

\makeatletter
\usetikzlibrary{intersections}

    %%
    %% There is no easy and clean way 
    %% to convert this all to expl3 (for instance underscore, under expl3 code regimè, 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@@sign{-}}{\def\dotncross@@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 \dx , \dy , \d; int \idx;
    \Ctmp{from} = (#3);
    \Ctmp{to} = (#4);
    \dx{tmp} = \Ctmpx{to} - \Ctmpx{from};
    \dy{tmp} = \Ctmpy{to} - \Ctmpy{from};
    \d{ang} = atan2(\dy{tmp},\dx{tmp});
    \Ctmp{1st} = (n#2-1);
    \Ctmp{last} = (n#2-\csuse{#2T});
    \idx{1st} = 1;
    \idx{last} = \csuse{#2T};
    \idx{crossing} = 1;
    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=\d{ang}]
      \foreach \aux in {\idx{1st},...,\idx{last}}{(#2-\aux) +(-#6/2,0) arc[start angle=\dotncross@@sign180,end angle=0,radius=#6/2]};
    \draw[rotate=\d{ang},line cap=round]
      \foreach \aux in {\idx{1st},...,\idx{last}}{(#2-\aux) +(-#6/2,0) arc[start angle=\dotncross@@sign180,end angle=0,radius=#6/2]};
  
    \gdef\dotncross@@tmpA{#3}
    \gdef\dotncross@@ListA{}
    \foreach \x in {\idx{1st},...,\idx{last}} {\xappto{\dotncross@@ListA}{\dotncross@@tmpA/n#2-\x,}\xdef\dotncross@@tmpA{n#2-\x}}
    \xappto{\dotncross@@ListA}{n#2-\idx{last}/#4}
    \foreach \xa/\xb in \dotncross@@ListA {\draw[line cap=round] (\xa) -- (\xb);}
  \fi
 }

  %%%%%%%%%%%%%%%%%%%
  %%%%
  %%%% 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,red,45)}
\def\dotncross@@coordnode(#1){coordinate(#1)  node[minimum size=1.2pt,inner sep=1.2pt](n#1){}}

\def\dotncross@@dotcoordpin(#1){\dotpincoord(#1,red,45)}
\def\dotncross@@dotcoordnode(#1){coordinate(#1)  node[circle,minimum size=1.2pt,inner sep=1.2pt,fill](n#1){}}

\def\dotncross@@odotcoordpin(#1){\odotpincoord(#1,red,45)}
\def\dotncross@@odotcoordnode(#1){coordinate(#1)  node[circle,minimum size=1.2pt,inner sep=1.2pt,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}{4}{#6}}
\def\dotncross@@pincaseC:#1:#2:#3:#4:#5;#6:{\dotncross@@pincoord{#1}{#2}{-45}{4}{#6}}
\def\dotncross@@pincaseD:#1:#2:#3:#4:#5;#6:{\dotncross@@pincoord{#1}{blue}{-45}{4}{#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=1.2pt,inner sep=1.2pt](n#1){}
  node[circle, #2,  inner sep=1.2pt, 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}]{}%
}
  
\showcoordsfalse        

