0

I would like to change below code to use chains join method instead of put a node in between. any ideas to implement it?

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.arrows, calc,chains}

\tikzset{ myarr/.style args={#1 -- #2}{ insert path={let \p1=($(#1)-(#2)$) in}, single arrow, draw=black, minimum width=20mm, minimum height={veclen(\x1,\y1)}, inner sep=0mm, single arrow head extend=1pt, }, every join/.style={->}, }

\begin{document} \begin{tikzpicture}[start chain=going right,node distance= 2cm and 2cm] \def\data{ A, B, C, D% } \foreach \p [count=\i from 1] in \data { \node[draw,on chain,join,minimum width=2cm,minimum height=4cm] (P\i) {\p}; } % move below logic to use join method \path (P1) -- (P2) node[midway,->,myarr={P1.east -- P2.west},single arrow] {}; \path (P2) -- (P3) node[midway,->,myarr={P2.east -- P3.west},single arrow] {}; \path (P3) -- (P4) node[midway,->,myarr={P3.east -- P4.west},single arrow] {}; \end{tikzpicture} \end{document}

Output: enter image description here

lucky1928
  • 4,151
  • It's not clear what you mean by the chains join method. You can use join=with to add connections back to earlier nodes in the chain, but these are edges rather than nodes and they connect a new node on the chain with an earlier one. You could adapt every join, maybe, to alter the way the nodes are joined. But you'd have to do that when specifying the chain rather than after. What exactly are you trying to do? – cfr Jan 04 '24 at 05:19

3 Answers3

4

I'm not sure what you're trying to do, but possibly you want something like the following?

\documentclass[border=10mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.arrows, calc,chains}

\tikzset{ myarr/.style args={#1 -- #2}{ insert path={let \p1=($(#1)-(#2)$) in}, single arrow, draw=black, minimum width=20mm, minimum height={veclen(\x1,\y1)}, inner sep=0mm, single arrow head extend=1pt, }, my arr/.style={ insert path={let \p1=(20mm,0pt) in}, single arrow, draw=black, minimum width=20mm, minimum height={veclen(\x1,\y1)}, inner sep=0mm, single arrow head extend=1pt, }, }

\begin{document} \begin{tikzpicture}[start chain=going right,node distance=2cm and 0cm] \def\data{ A, B, C, D% } \foreach \p [count=\i from 1,remember=\i as \ilast] in \data { \edef\tempa{1}\edef\tempb{\i}% \ifx\tempa\tempb\relax \else \node (A-\ilast-\i) [draw,on chain,my arr] {}; \fi \node[draw,on chain,join,minimum width=2cm,minimum height=4cm] (P\i) {\p}; } \end{tikzpicture} \end{document}

arrow nodes on chain

cfr
  • 198,882
1

A small variation of nice @cfr answer.

  • Macro join is intended (it seems so) only for drawing arrows (of any kind) between nodes, but it is not able to insert nodes between them.
  • Due to aforementioned you cannot insert nodes with single arrow shape between main nodes in chain by macro join. They can be inserted only as normal nodes in chain.
  • That single arrow node can fit nicely between two main nodes in chain, you need to define its style accordingly (see MWE below).
  • MWE:
\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc, chains,
                shapes.arrows}

\begin{document} \begin{tikzpicture}[ node distance = 0mm, start chain = going right, SA/.style = {% single arrow single arrow, single arrow head extend=3mm, draw, minimum width=20mm, minimum height=20mm, inner sep=0mm, node contents=\vphantom{A}, on chain }, N/.style = {draw, semithick, on chain, minimum width=2cm, minimum height=4cm} ] \def\data{A, B, C, D} \foreach \i [count=\j] in \data { \node[N] {\i}; \ifnum\j<4
\node[SA];
\fi } \end{tikzpicture} \end{document}

enter image description here

Zarko
  • 296,517
  • Good, so it's just like a node on chain, how can I make the big arrows half width? – lucky1928 Jan 04 '24 at 14:25
  • @lucky1928, just accordingly set arrows style and if needed, also change node distance accordingly (if I correctly understood you). If you have new problem, ask new question where explain what you like to change in my solution (the best is with sketch). – Zarko Jan 04 '24 at 15:02
1

You can place a node via a join on a chain by simply setting up a to path that does just that: place a node.

Inside a to path, you have access to \tikztostart and \tikztotarget – as well as \tikztonodes but we're going to ignore this here … or do you need text somewhere?

The difference can then be calculated as before, as can its veclen and, additionally, also its direction/angle via atan2. The results can then be used with a node as before which is now the only (visual) output of the to path.

This is all done in the myarr with anchors style:

\tikzset{
  myarr with anchors/.style 2 args={
    to path={
      let \p0=($(\tikztotarget.#2)-(\tikztostart.#1)$) in
      node[myarr node,
           minimum height={veclen(\x0,\y0)},
           shape border rotate={atan2(\y0,\x0)}] at (\tikztostart.#1) {}}}}

For simple chains, it is then as easy as

\tikz[
  start chain=going right, node distance=2cm and 2cm,
  every join/.style={myarr with anchors={east}{west}},
  every on chain/.append style={draw, minimum width=2cm, minimum height=4cm}]
\node foreach \t in {A, ..., D} [on chain, join]{\t};

I do like more automatic approaches where it will find the points on the border on its own.

For this, I provide the myarr style which uses an edge to find the points on the border and then uses these in the same calculation as before.

Optionally, it does also accept two arguments that are either empty (automatic approach or not a node) or contain an anchor specification (with the .).


Reference: Can we use `let` (from `TikZ`) inside a node's style definition?.

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{shapes.arrows, calc, chains}
\tikzset{
  myarr node/.style={
    shape=single arrow, draw=black, minimum width=20mm, anchor=tail,
    shape border uses incircle, single arrow head extend=+1pt,
    inner sep=+0pt, outer sep=+0pt},
  %
  myarr with anchors/.style 2 args={
    to path={
      let \p0=($(\tikztotarget.#2)-(\tikztostart.#1)$) in
      node[myarr node,
           minimum height={veclen(\x0,\y0)},
           shape border rotate={atan2(\y0,\x0)}] at (\tikztostart.#1) {}}},
  %
  myarr/.default={}{},
  myarr/.style 2 args={
    to path={
      \expanded{
        (\tikztostart#1) edge[path only, overlay, line to]
          coordinate[at start] (@start)
          coordinate[at end]   (@end) (\tikztotarget#2)}
      let \p0=($(@end)-(@start)$) in
      node[myarr node,
           minimum height={veclen(\x0,\y0)},
           shape border rotate={atan2(\y0,\x0)}] at (@start) {}}}}
\begin{document}
\pgfmathsetseed{872607}
\tikz[
  start chain=going right, node distance=2cm and 2cm,
  every join/.style={myarr with anchors={east}{west}},
  every on chain/.append style={draw, minimum width=2cm, minimum height=4cm}]
\node foreach \t in {A, ..., D} [on chain, join]{\t};

\tikz[ start chain=going right, node distance=2cm and 2cm, every join/.style=myarr, every on chain/.append style={draw, minimum width=2cm, minimum height=4cm}] \node foreach \t in {A, ..., D} [on chain, join]{\t};

\tikz[ start chain=going above right, node distance=.4cm and 2cm, every join/.style=myarr, every on chain/.append style={draw, circle, minimum size=2cm}] \node foreach \t in {A, ..., D} [on chain, join, shift={(3rand, 3rand)}]{\t};

\tikz[ start chain=going above right, node distance=.4cm and 2cm, every join/.style={myarr={.north east}{.south west}}, every on chain/.append style={draw, minimum width=2cm, minimum height=1cm}] \node foreach \t in {A, ..., D} [on chain, join]{\t}; \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821