4

Goal

I'm trying to connect the nodes of my graph using a horizontal-vertical-horizontal line.

MWE

Consider the following example:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{graphs, calc}

\begin{document} \begin{tikzpicture} \graph[left anchor=east, right anchor=west] { a -- { b, c } }; \end{tikzpicture} \end{document}

What argument do I need to pass to \graph to customize my edges, and how, to go from this:

Current graph, produced with code above

to this (not to scale):

enter image description here

My ideas

I tried specifying the key /tikz/graphs/new --, but I'm not sure how to do this. My main idea was to add the following to the previous code:

...
\graph[..., new --={\draw[#3] (#1) -| ($(#1)!.5!(#2)$) |- (#2) #4;}] {
...

and variants of that, trying to specify my function in various ways:

\graph[..., new --/.code={...}] { % or /.code 4 args or /.style
---------------------------------------------------------------------------
\graph[..., every new --={...}] { % or /.code or /.code 4 args or /.style or nothing
---------------------------------------------------------------------------
\tikzset{ % This seemed to be a good lead too
    manhattan/.code 4 args={\draw[#3] (#1) -| ($(#1)!.5!(#2)$) |- (#2) #4;},
}

... \graph[..., new --=manhattan] { % or /tikz/manhattan


\pgfkeys{/user/manhattan/.code 4 args={...}} % Same use as above

I also tested these ideas specifying the /tikz/graphs/default edge kind key instead of /tikz/graphs/new --.

Here are the two recurring error messages I encountered during my quest:

// Trying to define a key with /.code 4 args
! Illegal parameter number in definition of \pgfkeys@temp.
<to be read again> 
                   3
l.7 ...[#3] (#1) -| ($(#1)!.5!(#2)$) |- (#2) #4;}]
                                                   {

// Directly in \graph ! Argument of \tikz@parse@calculator has an extra }. <inserted text> \par l.11 ...#3] (#1) -| ($(#1)!.5!(#2)$) |- (#2) #4;}] { ?

Anyway, I'm lost, so thanks for any help here !

Jux
  • 43
  • 3
  • 3
    Welcome to TeX.SE! Nice first question, hope someone can answer soon – JamesT Jun 19 '23 at 20:19
  • 2
    You need to do new --/.code n args={4}{…} and then #1 ist the start node, #2 is the target, #3 is the edge's options and #4 are the nodes. Though, I'd suggest just setting the right to path (for example in /tikz/every new --) or just for all edges. – Qrrbrbirlbel Jun 19 '23 at 20:45
  • 2
    new --/.style={/user/manhattan=#1} might work, too , if you want to use that custom style. But .code 4 args is not a correct handler. Pgfkeys only knows .code (one argument), .code 2 args (2), .code n args={<n>}{…} where n is less or equal 9 or code args={???}{…} where you can give any argument specification (just like \def.) – Qrrbrbirlbel Jun 19 '23 at 20:50
  • Oooh I see, I was close but didn't understand this subtility ! – Jux Jun 20 '23 at 14:32

1 Answers1

2

The new -- key will be called with four arguments: {⟨left node⟩}{⟨right node⟩}{⟨edge options⟩}{⟨edge nodes⟩}.

This means you will have to overwrite it the same way. PGFKeys provides four code handlers:

  1. .code for zero or one argument,
  2. .code 2 args for two arguments,
  3. .code args for a custom argument specification and
  4. .code n args for a variable number of arguments (zero to nine)

and a bunch of variants (.ecode, .add code, etc).

You will need to use code n args:

new --/.code n args={4}{\draw[#3] (#1\tikzgraphleftanchor) -| ($(#1)!.5!(#2)$)
                                               |- #4 (#2\tikzgraphrightanchor);}

I took the liberty to include the anchor specification (although they are not necessary with these connections because TikZ would automatically use the same anchor.


You could also adjust the /tikz/every new -- style to use a custom to path, say

\tikzset{
  every new --/.style={
    to path={
      -|($(\tikztostart)!.5!\tikztotarget)$) -| (\tikztotarget) \tikztonodes
    }
  }
}

but you wouldn't have access to the pure node name (or you need to parse it out again) when \tikztostart/\tikztotarget includes them.

The same applies to the edges key that sets all edges to the same style.

Interestingly, you can set the new -- key as part of the options of the --[<opt>] syntax. Though, using it with -> would not change anything.

Code

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, graphs, calc}
\tikzgraphsset{
  |-| connection/.style={
    new --/.code n args={4}{\draw[##3] (##1\tikzgraphleftanchor) -| ($(##1)!.5!(##2)$) |- ##4 (##2\tikzgraphrightanchor);}}}
\begin{document}
\tikz
\graph[left anchor=east, right anchor=west,
  new --/.code n args={4}{\draw[#3] (#1\tikzgraphleftanchor) -| ($(#1)!.5!(#2)$) |- #4 (#2\tikzgraphrightanchor);}
] {
    a -- { b, c } --[complete bipartite] {d, e, f}
  };

\tikz[>=Stealth] \graph[left anchor=east, right anchor=west] { a -- { b, c } --[|-| connection, complete bipartite] {d, e, f} ->[|-| connection, complete bipartite] {g, h} }; \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
  • Thank you so much for the detailed answer ! I'll go the first way, it's a bit cleaner in IMO. Just out of curiosity, why do you need double # in |-| connection/.style definition ? – Jux Jun 20 '23 at 14:28
  • 1
    Well, you can just do graph[|-| connection] or \tikzgraphsset{every graph/.append style={|-| connection}}. Declaring it every time you need it, might not be the best approach. The doubling of # is a TeX thing and is required when nesting defintions. Here, the new -- definition is nested inside the definition of |-| connection where #1 would be the argument that is given to the key |-| connection (which is not used however). – Qrrbrbirlbel Jun 20 '23 at 14:33
  • Oh I see ! And in my case, I only have one very large graph, so it's not a problem to define on the fly :) – Jux Jun 20 '23 at 15:24