
Meine Frage folgteine meiner vorherigen Fragen.
Hier ist mein aktueller Code:
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{matrix,positioning}
\newcommand{\multilinkstoonenode}[3]{
\begin{scope}[x=1em,y=1em]
\newdimen\xend
\newdimen\yend
\path (#2.west);
\pgfgetlastxy{\xend}{\yend}
\foreach \i in {#1} {
\newdimen\xstart
\newdimen\ystart
\path (\i.east);
\pgfgetlastxy{\xstart}{\ystart}
\coordinate (1) at ({\xend-#3 em},\ystart);
\coordinate (2) at ({\xend-#3 em},\yend);
\ifdim\ystart=\yend
\draw[->] (\i.east)--(#2.west);
\else
\draw[->,rounded corners] (\i.east)--(1)--(2)--(#2.west);
\fi
}
\end{scope}
}
% \multilinkstomultiplenodes{list of left nodes}{list of right nodes}{distance between the right nodes and the right vertical line}{distance between the left vertical line and the right vertical line}
\newcommand{\multilinkstomultiplenodes}[4]{ %TODO
}
\begin{document}
\tikzset{
basic/.style={
draw,
rounded corners=2pt,
thick,
text width=8em,
align=flush center,
node distance=2em
}
}
\begin{tikzpicture}[]
\matrix[row sep=2em, column sep=4em, every node/.style={basic}] {
\node(n1){Text}; & \node(n6){another text}; \\
\node(n2){one thing}; & \node(n7){again text}; \\
\node(n3){text}; & \node(n8){text}; \\
\node(n4){text}; & \node(n9){text}; \\
\node(n5){text}; & \node(n0){text}; \\
};
\multilinkstoonenode{n1,n2}{n6}{3}
%to modify
\multilinkstoonenode{n2,n3,n4,n5}{n7}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n8}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n9}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n0}{1}
% Expected: \multilinkstomultiplenodes{n2,n3,n4,n5}{n2,n3,n4,n5}{1}{1}
\end{tikzpicture}
\end{document}
Und das Ergebnis:
Ich versuche jetzt, einen neuen Befehl zu definieren, sodass er folgendermaßen aussieht:
Ich muss in der Lage sein, den Abstand zwischen den rechten Knoten und der rechten vertikalen Linie sowie den Abstand zwischen der linken vertikalen Linie und der rechten vertikalen Linie zu bestimmen. Die mittlere horizontale Linie muss relativ zu den rechten Knoten zentriert sein.
Ich bin derzeit völlig ratlos, wie ich weiter vorgehen soll.
Antwort1
Hier ist ein Vorschlag. Er enthält einen Stil connect through
, der prüft, ob eine Strecke horizontal ist (um Probleme mit abgerundeten Ecken zu vermeiden) und einen anderen Stil, multiconnect
der mehrere Verbindungen herstellt. (Ich bin im Allgemeinen kein großer Fan vom Schreiben von Makros, aber ich denke, man sollte Stile für Ti verwenden.kZ. Um das klarzustellen, ich habe mir Jaspers Antwort aus diesem Grund nicht angesehen. Es kann sein, dass einige Dinge parallel sind oder nicht, aber wenn ja, war er zuerst da. Ich bin nicht in der Stimmung, diese Makros durchzusehen, tut mir leid.)
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{matrix,positioning,fit,calc}
\begin{document}
\tikzset{
basic/.style={
draw,
rounded corners=2pt,
thick,
text width=8em,
align=flush center,
node distance=2em
},
horizontal stretch/.initial=1em,
connect through/.style={to path={
let \p1=($(\tikztostart)-(#1)$),\p2=($(\tikztotarget)-(#1)$),
\n1={abs(\y1)},\n2={abs(\y2)} in
\ifdim\n1<1pt
(\tikztostart) -- (#1)
\else
[/utils/exec=\pgfmathsetmacro{\mysign}{sign(\x1)}]
(\tikztostart) -|
([xshift=\mysign*\pgfkeysvalueof{/tikz/horizontal stretch}/2]#1)
-- (#1)
\fi
\ifdim\n2<1pt
(#1) -- (\tikztotarget)
\else
[/utils/exec=\pgfmathsetmacro{\mysign}{sign(\x2)}]
(#1) --
([xshift=\mysign*\pgfkeysvalueof{/tikz/horizontal stretch}/2]#1)
|- (\tikztotarget)
\fi
}},
multiconnect/.style n args={3}{insert path={%
[/utils/exec={\foreach \X [count=\Y] in {#2}
{\ifnum\Y=1
\xdef\LstTargets{(\X)}
\else
\xdef\LstTargets{\LstTargets (\X)}
\fi}}]
node[fit=\LstTargets,inner sep=0pt] (auxR){}
($(#1.east)!#3!(auxR.west)$) coordinate (auxM)
foreach \Y in {#2}
{
(#1.east) edge[connect through=auxM|-auxR,-latex] (\Y)
}}}
}
\begin{tikzpicture}[]
\matrix[row sep=2em, column sep=4em, every node/.style={basic}] {
\node(n1){Text}; & \node(n6){another text}; \\
\node(n2){one thing}; & \node(n7){again text}; \\
\node(n3){text}; & \node(n8){text}; \\
\node(n4){text}; & \node(n9){text}; \\
\node(n5){text}; & \node(n0){text}; \\
};
\foreach \XX in {n1,n2}
{\draw[rounded corners,multiconnect={\XX}{n6}{0.5}] ;}
\foreach \XX in {n2,n3,n4,n5}
{\draw[rounded corners,multiconnect={\XX}{n7,n8,n9,n0}{0.5}] ;}
\end{tikzpicture}
\end{document}
Antwort2
Ich verstehe die Regeln nicht ganz, nach denen der OP die Knoten verbinden möchte, und ich bin ziemlich sicher, dass es einen einfacheren Weg (über Pakete) gibt, um das folgende Ergebnis zu erzielen, aber vielleicht hilft der folgende Code dabei, eine gute Lösung zu finden.
Die verbindende horizontale Linie ist nicht relativ zu den Knoten auf der rechten Seite zentriert, wie vom OP gewünscht, sondern relativ zu den Knoten auf der linken Seite (sonst wäre das Ergebnis der Version des OP ähnlich).
(Führt zu etwas hässlichen Verbindungen, wenn nur zwei Knoten miteinander verbunden werden (1:1).)
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{matrix,positioning,calc}
\newcommand{\multilinkstoonenode}[3]{
\begin{scope}[x=1em,y=1em]
\xdef\j{#2}
\foreach \c [count=\x] in {#1} {
\ifnum\x=1
\xdef\xtop{\c}
\xdef\xbottom{\c}
\else
\xdef\xbottom{\c} % redefining \xbottom until end of loop
\fi
}
\coordinate (left) at ([xshift=#3 em]$(\xtop.east)!0.5!(\xbottom.east)$);
\coordinate (right) at ([xshift=-#3 em]$(#2.west)!0.5!(#2.west)$);
\foreach \i in {#1} {
\draw[->,rounded corners]
(\i.east)-|(left)
-|(right)
--(\j.west);
}
\end{scope}
}
\begin{document}
\tikzset{
basic/.style={
draw,
rounded corners=2pt,
thick,
text width=8em,
align=flush center,
node distance=2em
}
}
\begin{tikzpicture}[]
\matrix[row sep=2em, column sep=4em, every node/.style={basic}] {
\node(n1){Text}; & \node(n6){another text}; \\
\node(n2){one thing}; & \node(n7){again text}; \\
\node(n3){text}; & \node(n8){text}; \\
\node(n4){text}; & \node(n9){text}; \\
\node(n5){text}; & \node(n0){text}; \\
};
\multilinkstoonenode{n1,n2}{n6}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n7}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n8}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n9}{1}
\multilinkstoonenode{n2,n3,n4,n5}{n0}{1}
\end{tikzpicture}
\end{document}
Ergebnis:
Bearbeiten
Ich habe eine neue Lösung gefunden, bei der das Makro zwei Listen von Knoten annimmt, die verbunden werden sollen. Dabei sind mir mehrere Probleme begegnet.
Erstens gibt es, wie der OP bereits in der oben verlinkten Frage herausgefunden hat, ein Problem, wenn wir versuchen, Knoten mit identischen Koordinaten mit Strichen zu verbinden, die abgerundete Ecken haben. Da die Knoten in unserem Fall automatisch generiert werden, können wir nicht vermeiden, dass Knoten die gleichen Koordinaten haben. Daher müssen wir die Y-Koordinate der Knoten des Verbindungspfads testen.
Dort stoßen wir auf das Problem von Rundungsfehlern. Ich habe versucht, dieses Problem zu lösen, indem ich die y-Koordinate durch 10 geteilt habe, um die letzte Ziffer abzuschneiden und den Rundungsfehler zu beseitigen.
Nun, vielleicht kann der folgende Code vereinfacht werden, aber er kann als Ausgangspunkt dienen …
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{matrix,positioning,calc}
\newcommand{\multilinkstoonenode}[3]{
\begin{scope}[x=1em,y=1em]
\xdef\j{#2}
\foreach \c [count=\x] in {#1} {
\ifnum\x=1
\xdef\xtop{\c}
\xdef\xbottom{\c}
\else
\xdef\xbottom{\c}
\fi
}
\foreach \d [count=\y] in {#2} {
\ifnum\y=1
\xdef\ytop{\d}
\xdef\ybottom{\d}
\else
\xdef\ybottom{\d}
\fi
}
\newdimen\xmiddle
\newdimen\ymiddle
\newdimen\xleft
\newdimen\yleft
\newdimen\xright
\newdimen\yright
\coordinate (right) at ([xshift=-#3 em]$(\ytop.west)!0.5!(\ybottom.west)$);
\coordinate (left) at ([xshift=#3 em]\xtop.east |- right);
\path(left);
\pgfgetlastxy{\xmiddle}{\ymiddle}
\pgfmathsetlengthmacro{\ymiddlex}{\ymiddle/10}
\foreach \i in {#1} {
\path(\i);
\pgfgetlastxy{\xleft}{\yleft}
\pgfmathsetlengthmacro{\yleftx}{\yleft/10}
\foreach \j in {#2} {
\path(\j);
\pgfgetlastxy{\xright}{\yright}
\pgfmathsetlengthmacro{\yrightx}{\yright/10}
\ifdim\yleftx=\ymiddlex
\draw[->](\i.east)--(\j.west);
\else
\draw[->,rounded corners]
(\i.east)-|(left)
--(right)
\ifdim\ymiddlex=\yrightx
--(\j.west);
\else
|-(\j.west);
\fi
\fi
}
}
\end{scope}
}
\begin{document}
\tikzset{
basic/.style={
draw,
rounded corners=2pt,
thick,
text width=8em,
text depth=0em,
align=flush center,
node distance=2em
}
}
\begin{tikzpicture}[]
\matrix[row sep=2em, column sep=4em, every node/.style={basic}] {
\node(n1){Text}; & \node(n6){another text}; \\
\node(n2){one thing}; & \node(n7){again text}; \\
\node(n3){text}; & \node(n8){text}; \\
\node(n4){text}; & \node(n9){text}; \\
\node(n5){text}; & \node(n0){text}; \\
\node(n10){text}; & \node(n11){text}; \\
\node(n20){text}; & \node(n21){text}; \\
\node(n30){text}; & \node(n31){text}; \\
};
\multilinkstoonenode{n1,n2}{n6}{.5}
\multilinkstoonenode{n2,n3,n4,n5}{n7,n8,n9,n0}{1.5}
\multilinkstoonenode{n10}{n11}{1}
\multilinkstoonenode{n20}{n21,n31}{1}
\end{tikzpicture}
\end{document}
Ergebnis:
Antwort3
Ich habe diesen Code verwendet:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usepackage{xstring}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}
\newcommand{\listbcs}[4]{
\tikzset{
barycentric setup/.code={\foreach \X [count=\Y] in {#1}
{\ifnum\Y=1
\xdef\baryarg{\X=1}
\else
\xdef\baryarg{\baryarg,\X=1}
\fi}},
barycentric list/.style={barycentric setup={#1},insert path={%
(barycentric cs:\baryarg)}}
}
\path[barycentric list={#1}] node[anchor=center,align=flush center,#2] (#3) {#4};
}
\newcommand{\multilinks}[4]{%
\begin{scope}[x=1em,y=1em]
\listbcs{#2}{}{bcright}{}
\newdimen\xright
\newdimen\ybc
\newdimen\dump
\path(bcright);
\pgfgetlastxy{\dump}{\ybc}
\getfirst{#2}
\path(#3em,0em);
\newdimen\xtemp
\pgfgetlastxy{\xtemp}{\dump}
\coordinate (midright) at ({\xnow-#3 em},\ybc);
\coordinate (midleft) at ({\xnow-#3em-#4em},\ybc);
\foreach \i in {#1} {
\foreach \j in {#2}{
\newdimen\ystart
\path (\i.east);
\pgfgetlastxy{\dump}{\ystart}
\newdimen\xmidl
\newdimen\xmidr
\path (midleft);
\pgfgetlastxy{\xmidl}{\dump}
\path (midright);
\pgfgetlastxy{\xmidr}{\dump}
\newdimen\yend
\path (\j.west);
\pgfgetlastxy{\dump}{\yend}
\coordinate (cl) at (\xmidl,\ystart);
\coordinate (cr) at (\xmidr,\yend);
\ifdim\ystart=\ybc\relax%
\ifdim\ybc=\yend\relax%
\draw[->] (\i.east)--(\j.west);%
\else\relax%
\draw[->,rounded corners] (\i.east)--(midright)--(cr)--(\j.west);%
\fi\relax%
\else\relax%
\ifdim\ybc=\yend\relax%
\draw[->,rounded corners] (\i.east)--(cl)--(midleft)--(\j.west);%
\else\relax%
\draw[->,rounded corners] (\i.east)--(cl)--(midleft)--(midright)--(cr)--(\j.west);%
\fi\relax%
\fi\relax%
}
}
\end{scope}
}
\newcommand{\getfirst}[1]{
\StrCount{#1}{,}[\numofelem]
\ifnum\numofelem>0\relax
\StrBefore[1]{#1}{,}[\myhead]
\else
#1
\fi
}
\begin{document}
\tikzset{
basic/.style={
draw,
rounded corners=2pt,
thick,
text width=8em,
align=flush center,
}
}
\begin{tikzpicture}
\matrix[row sep=2em, column sep=4em, every node/.style={basic}] {
\node(a){text}; & \node(c){text}; \\
\node(b){text}; & \node(d){text}; \\
\node(e){text}; & \node(f){text}; \\
};
\multilinks{a,e}{c,d,f}{1}{1}
\end{tikzpicture}
\end{document}