0

i intent to create the command \graphEdge to streamline drawing graphs edges, it would take a list of arguments separated by , the function would then divide the arguments and iterate on it, creating a new \draw for each minus the last one.

On the mwe there is some very rough idea of the function implementation, and an example of usage.

MWE

\documentclass{standalone}
\usepackage{xparse}
\usepackage{tikz}
\NewDocumentCommand\graphEdge{
    s % #1 - dashed
    > {\SplitList{,}}
    o % #2 - position options
    > {\SplitList{,}}
    o % #3 - draw options
    >{\SplitList{,}}
    m % #4 - annotations
    >{\SplitList{,}}
    m % #5 - nodes
}{
    % i = interator
    \IfValueT{#5[i+1]}{
        \draw[->,\IfBooleanT{#1}{dashed,}\IfValueT{#3[i]}{#3[i]}]%
        (#5[i]-x) --node[sloped,\IfValueTF{#2[i]}{#2[i]}{above}] {\(#4[i]\)}%
        (#5[i+1]-x);
    }
}

\begin{document}

\begin{tikzpicture}

% ======================= Nodes ====================== %

% 1,2,3
\node (1-x) at (0, 0) {1};
\node (2-x) at (1, 1) {2};
\node (3-x) at (2, 1) {3};
\node (4-x) at (1,-1) {4};

% ======================= Edges ====================== %

% \graphEdge{A,B}{1,2,3}
\draw[->] (1-x) --node[sloped,above]{\(A\)} (2-x);
\draw[->] (2-x) --node[sloped,above]{\(B\)} (3-x);
% \graphEdge*{C,D}{1,4,3}
\draw[->,dashed] (1-x) --node[sloped,above]{\(C\)} (4-x);
\draw[->,dashed] (4-x) --node[sloped,above]{\(D\)} (3-x);

\end{tikzpicture}

\end{document}

Felipe9
  • 309
  • 1
    Instead of your command, wouldn't be \graphEdge{[below]A, [above]B}{1, 2, 3} nicer? With the graphs library you can just do graph[use existing nodes] {1 ->["A"] 2 ->["B"'] 3} and you see directly which node is placed along which edge. – Qrrbrbirlbel Jun 09 '23 at 16:53
  • I wish that was a solution, i had a whole problem and in the end gave up on that, you can have a look at the progress here – Felipe9 Jun 10 '23 at 14:11

1 Answers1

1

You can use l3clist's \clist_item:nn to access elements in a list directly, since it will be returned with an \unexpanded, we can safely use the .expanded handler to allow fore more than one option per item (otherwise, it would try to find the key blue, ' in the example below).

The elements of #4 is used directly as the list for one \foreach loop where \i counts from 1 and \j counts from 2, though you can just use \i + 1 and l3clist will evaluate that for you.

Instead of setting above by default, I'm using auto = left which can be swapped to auto = right by using the ' key. (Although, you can set above and just define '/.style = below just for your nodes.)

Code

\documentclass[tikz]{standalone}
\ExplSyntaxOn
\NewDocumentCommand\graphEdge{
    s % #1 - dashed
    o % #2 - position options
    o % #3 - draw options
    m % #4 - annotations
    m % #5 - nodes
}{
  \foreach[count=\i,count=\j from 2]\VALUE in {#4}
    \draw[
      ->,
      \IfBooleanT{#1}{dashed},
      style/.expanded=\IfValueT{#3}{\clist_item:nn{#3}{\i}}]
      (\clist_item:nn{#5}{\i}-x)
       to node[
         sloped,
         auto=left,
         style/.expanded=\IfValueT{#2}{\clist_item:nn{#2}{\i}}]{\(\VALUE\)}
      (\clist_item:nn{#5}{\i+1}-x);
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\node (1-x) at (0, 0) {1}; \node (2-x) at (1, 1) {2};
\node (3-x) at (2, 1) {3}; \node (4-x) at (1,-1) {4};

\graphEdge{A,B}{1,2,3} \graphEdge*[', {blue, '}][, bend right]{C,D}{1,4,3} \end{tikzpicture} \end{document}

Output

enter image description here


Here's the same example with the graphs library, unfortunatley I ran into a bug where name suffix does not consider the target node properly. The proposed fix is included in the code below.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs, quotes}
\tikzset{math node/.style={execute at begin node=$, execute at end node=$}}
\makeatletter % https://github.com/pgf-tikz/pgf/issues/1251#issuecomment-1486886842
\def\tikz@@to@or@edge@@coordinate(#1){\tikz@scan@one@point\tikz@to@use@last@coordinate@as@target(#1)\tikz@to@or@edge@function}
\def\tikz@to@use@last@coordinate@as@target#1{\iftikz@shapeborder\edef\tikztotarget{\tikz@shapeborder@name}\else\edef\tikztotarget{\the\tikz@lastx,\the\tikz@lasty}\fi}
\makeatother
\newcommand*\graphEdges[2][]{%
\path[name suffix=-x,#1]graph[
  use existing nodes,edge quotes={sloped,auto=left,math node}]{#2};}
\begin{document}
\begin{tikzpicture}
\node (1-x) at (0, 0) {1}; \node (2-x) at (1, 1) {2};
\node (3-x) at (2, 1) {3}; \node (4-x) at (1,-1) {4};

\graphEdges{ 1 ->["A"] 2 ->["B"] 3, {[edge = dashed] 1 ->["C"' bend right] 4 ->["D"' blue] 3, } } \end{tikzpicture} \end{document}

Qrrbrbirlbel
  • 119,821
  • This was exactly what i was looking for, i have heard about the programming interface but this is my first contact with it. Thanks! – Felipe9 Jun 10 '23 at 15:10