
cómo cambiar el código para que no se superponga como en la imagen, si es posible que la primera salida vaya a la segunda sin superponerse a otras filas. En segundo lugar, existe otra posibilidad de crear una nueva línea dentro de la sección if.
gracias por tu apoyo.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows,shapes}
\begin{document}
\begin{tikzpicture}[node distance = 1.2cm, auto]
\tikzstyle{startstop} = [rectangle, rounded corners, minimum width=3cm, minimum height=1cm,text centered, draw=black, fill=red!30]
\tikzstyle{io} = [trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=blue!30]
\tikzstyle{process} = [rectangle, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=orange!30]
\tikzstyle{decision} = [diamond, minimum width=3cm, minimum height=1cm, text centered, draw=black, fill=green!30]
\tikzstyle{arrow} = [thick,->,>=stealth]
% Place nodes
\node (start) [startstop] {Start};
\node (in1) [io, below of=start] {Input: f(), a, b, $\varepsilon$};
\node (pro1) [process, below of=in1] {c=(a+b)/2};
\node (if1) [decision, below of=pro1, yshift=-1.5cm] {if: f(a)*f(b)$>$0};
% \node (pro1) [process, below of=in1] {Process 1};
\node (dec1) [decision, below of=if1, yshift=-4cm] {While: f(c) $\not=$ 0 \& $|$f(b) - f(a)$|$ $> \delta$};
\node (pro1a) [process, below of=dec1, yshift=-3cm] {c=(a+b)/2};
\node (dec2) [decision, below of=pro1a,yshift=-1.75cm] {if: f(a)*f(c) $<$ 0};
\node (pro2) [process, left of=dec2, xshift=-3cm] {b=c};
\node (pro3) [process, below of=dec2, yshift=-1.5cm] {a=c};
\node (out1) [io, below of=pro3] {Output: H, V, T};
\node (out2) [io, left of=out1,xshift=-4.5cm] {Output: H, V, T};
\node (pro4) [process, below of=out1] {Plot:H on T and V on T};
\node (stop) [startstop, below of=pro4] {Stop};
\draw [arrow] (start) -- (in1);
\draw [arrow] (in1) -- (pro1);
\draw [arrow] (pro1) -- (if1);
\draw [arrow] (if1) -- node {False} (dec1);
\draw [arrow] (dec1) -- node {True} (pro1a);
\draw [arrow] (pro1a) -- (dec2);
\draw [arrow] (dec2) -- node {False}(pro3);
%\draw [arrow] (if1) -- ++(-5.5,-0) -- ++(-1.5,0) |- node[below right] {True} (out2)
\draw [arrow] (if1) -| node [above right] {True} (out2);
\draw [arrow] (pro2) |- (dec1);
\draw [arrow] (pro3) -- ++(-3.5,-0) -- ++(-2.5,0) |- (dec1);
\draw [arrow] (dec2) -- node {True} (pro2);
\draw [arrow] (dec1) -- ++(2.5,-0) -- ++(3,0) |- node[right] {False} (out1);
\draw [arrow] (out1) -- (pro4);
\draw [arrow] (out2) |- (stop);
\draw [arrow] (pro4) -- (stop);
\end{tikzpicture}
\end{document}
Pregunta adicional: Cómo decirle a LaTex que dibuje entre dos procesos como en el ejemplo de la imagen
Respuesta1
Supongo que te puede gustar :-)
- El diagrama de flujo anterior está escrito casi desde cero.
- En lugar de nodos obsoletos,
\tikzstyle
los estilos se definen como opciones detikzpicture
. - Sin embargo, si prefiere haberlos definido en el preámbulo del documento, puede pasar a
\tikset{<styles definitions>}
colocarlos en el preámbulo. - El código del diagrama de flujo se vuelve más conciso y claro si se emplea Ti en la posición de la rama principal.kBiblioteca Z
chains
con su macrojoin
- La ubicación consistente de los nodos en la cadena, así como de otros nodos, proporciona el uso de Ti.kBiblioteca Z
positioning
cuya sintaxis...=of <node name>
(en lugar de la obsoleta... of = <node name>
utilizada en su MWE) define distancias entre los bordes de los nodos. De esta manera se evitan sus eventuales superposiciones. - Me tomé un poco de libertad y en algunos nodos escribí texto en varias líneas.
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{chains,
positioning,
quotes,
shapes.geometric}
\makeatletter
\tikzset{suppress join/.code={\def\tikz@after@path{}}}
\makeatother
\begin{document}
\begin{tikzpicture}[
node distance = 6mm and 12mm,
start chain = A going below,
base/.style = {draw, fill=#1,
minimum width=34mm, minimum height=7mm, align=left,
font=\ttfamily},
startstop/.style = {base=red!30, rounded corners},
process/.style = {base=orange!30},
io/.style = {base=blue!30,
trapezium, trapezium stretches body,
trapezium left angle=70, trapezium right angle=110},
decision/.style = {base=green!30, diamond, aspect=1.5},
arr/.style = {semithick,-latex}
]
% nodes in chain
\begin{scope}[nodes={on chain=A, join=by arr}]
\node [startstop] {Start}; % name: A-1
\node [io] {Input:\\ f(), a, b, $\varepsilon$};
\node [process] {c=(a+b)/2};
\node [decision] {if:\\ f(a)*f(b)$>$0}; % A-4
\node [decision] {While:\\ % A-5
f(c) $\not=$ 0 \& \\
$|$f(b) - f(a)$|$ $> \delta$};
\node [process] {c=(a+b)/2};
\node [decision] {if:\\ f(a)*f(c)\textless 0}; % A-7
\node [process] {a=c};
\node [io, suppress join]
{Output: H, V, T};
\node [process] {Plot:\\ H on T and V on T};
\node [startstop] {Stop};
\end{scope}
\node (a) [process, left=of A-7] {b=c};
\node (b) [io, left=of A-9] {Output: H, V, T};
%
\path (A-4) edge["False"] (A-5)
(A-5) edge["True"] (A-6)
(A-7) edge["False"] (A-8)
(A-7) edge["True"] (a)
;
\draw[arr] (A-5.east) to["false"] ++ (2,0) |- (A-9);
\draw[arr] (a) |- (A-5);
\draw[arr] (A-8) -| ([shift={(-1em,-0)}] a.west) % <---
|- (A-5);
\draw[arr] (A-4) -| node[pos=0.1, above] {True}
([shift={(-2em,-2em)}] a.south west) % <---
|- (b);
\draw[arr] (b) |- (A-10);
\end{tikzpicture}
\end{document}
\end{tikzpicture}
\end{document}
Apéndice:
La otra respuesta de @Qrrbrbirlbel proporciona una idea intrigante, por lo que aquí hay una prueba de su adaptación a la propuesta anterior. En comparación con la propuesta original, esto cambió lo siguiente:
- eliminado
scope
para poner nodos en la cadena - La macro
join
(que aquí no funciona) se reemplaza con\foreach
un bucle. - considere la idea de @Qrrbrbirlbel sobre dibujar
decision
nodos - camino usado
-|-
coordinado donde sea apropiado (sensible) - Las etiquetas del resultado de la decisión se escriben como opciones de nodos.
- Se cambia el nombre de los nodos (eso puede distinguirse fácilmente de los nombres en la respuesta original)
- Se agregó una flecha de bucle adicional a la derecha (a pesar de que, en mi opinión, es lógico incorrecto)
La imagen resultante es un código más compacto y no muy diferente que puede ser fácil de entender:
\documentclass[border=3.141592]{standalone}
\usepackage{tikz}
\usetikzlibrary{
arrows.meta, % arrow tips
chains, % start chain, on chain
ext.paths.ortho, % -|- and |-| path operations
positioning, % ...=of <node>
shapes.geometric % for diamond at "if" node
}
\begin{document}
\begin{tikzpicture}[auto,
node distance = 6mm and 12mm,
start chain = A going below,
arr/.style = {semithick,-Stealth},
base/.style = {draw=#1, semithick, fill=#1!25,
text width=32mm, minimum height=7mm, align=center,
font=\ttfamily,
on chain=A
},
be/.style = {% BeginEnd
base=red, rounded corners},
D/.style = {diamond, draw=#1, fill=#1!50, inner sep=2mm, anchor=center},
if/.style = {base=teal, align=left,
label={[D=teal]north east:}},
lbl/.style = {inner ysep=2pt, font=\small, text=black!75},
lb/.style = {label={[lbl, anchor=north west]south:#1}},
ll/.style = {label={[lbl, anchor=south east]west:#1}},
lr/.style = {label={[lbl, anchor=south west]east:#1}},
pc/.style = {% ProCess
base=orange},
io/.style = {base=blue,
trapezium, trapezium stretches body,
trapezium left angle=70, trapezium right angle=110},
%
every chain label/.style={inner sep=1mm, font=\footnotesize},
off chain/.code={\def\tikz@lib@on@chain{}} % <== defined interruption of chain
]
% nodes
\node [be] {Start}; % name: A-1
\node [io] {Input:\\ f(), a, b, $\varepsilon$};
\node [pc] {c=(a+b)/2};
\node [if,
ll=True,
lb=False] {if:\\ f(a)*f(b)$>$0}; % A-4
\node [if,
lb=False,
lr=True] {While:\\ % A-5
f(c) $\not=$ 0 \& \\
$|$f(b) - f(a)$|$ $> \delta$};
\node [pc] {c=(a+b)/2};
\node [if,
lb=False,
ll=True] {if:\\ f(a)*f(c)\textless 0}; % A-7
\node [pc] {a=c};
\node [io]
{Output: H, V, T};
\node [pc] {Plot:\\ H on T and V on T};
\node [be] {Stop}; % A-11
%% nodes out of chain
\node [pc, off chain,
left=of A-7] {b = c}; % A-12
\node [io, off chain,
left=of A-9] {Output: H, V, T}; % A-13
%%% arrows in main branch
\foreach \i [evaluate=\i as \j using int(\i+1)] in {1,2,...,7, 9,10}
\draw[arr] (A-\i) -- (A-\j);
%%%% arrows on the left
\draw[arr] (A-4) -|-[distance=54mm] (A-13.west); % node distance+text width+2*(inner sep)+distance
\draw[arr] (A-7) -- (A-12);
\draw[arr] (A-8.west) -|-[distance=-50mm] ([yshift=2mm] A-5);
\draw[arr] (A-12) |- ([yshift=-2mm] A-5.west);
\draw[arr] (A-13) |- (A-10);
%%%% arrows on the right
\draw[arr] (A-5) -|-[distance=8mm] (A-9.east);
\draw[arr] (A-10) -|-[distance=12mm] (A-3.east);
\end{tikzpicture}
\end{document}
Respuesta2
Como siempre, hay muchas maneras.
- para declarar nodos,
- para colocar nodos y
- para conectarlos.
Aquí hay dos soluciones.
El primero usa la graphs
biblioteca para declarar nodos y conectarlos mientras que el chains
y la positioning
biblioteca se usa para colocarlos.
La segunda solución utiliza a \matrix
para colocar los nodos en una cuadrícula. (Desafortunadamente, no se puede usar matrix of nodes
fácilmente \\
dentro de un nodo. Pero para esto, proporcionaré el \n
atajo). También
se graphs
usa aquí para conectar los nodos. edge
En mi opinión, simplemente proporciona una sintaxis más sencilla que la operación de ruta.
En ambas soluciones, el nombre proporcionado, por ejemplo st'0
, IO'1
, etc., también se usa para diseñar el nodo, todo lo que viene antes '
se usa para un estilo, por ejemplo style st
, style IO
, etc. En la \matrix
solución, este nombre de pila no se usa con la name
clave pero la alias
clave para que los nodos de la matriz aún tengan su <matrix name>-<row>-<column>
nombre disponible. Esto permitiría convertirlo matrix
en un tikzcd
diagrama. (Sin embargo, creo que la descripción general se pierde si también mezclamos \ar
comandos en la matriz).
La show node names
tecla se puede utilizar para mostrar el nombre de los nodos principales en la esquina superior izquierda:
No me gusta mucho la forma del diamante. Sugeriré un chamfered rectangle
con la STYLE if=chamfered
opción:
Con STYLE if=labeled
podemos tener un pequeño diamante en la esquina superior derecha de un rectángulo normal:
Como siempre con este tipo de diagramas, estoy usando la ext.paths.ortho
biblioteca de mitikz-ext
paquete. Proporciona la operación de ruta r-rl
que primero dibuja una línea horizontal hacia la derecha, luego una línea vertical hasta el nodo objetivo y una línea horizontal de regreso al objetivo.
Código
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{
arrows.meta, % arrow tips
shapes.geometric, % diamond, trapezium
quotes, % "nodes" on edges
positioning, % left=of
ext.paths.ortho, % r-rl and r-lr path operations
shapes.misc, % chamfered rectangle
%
matrix, % matrix of nodes
chains, % start chain, on chain
graphs, % \graph
}
\tikzset{
COMMON/.style={
/utils/exec=\def\|{\textbar},
node distance = 7mm and 1cm, row sep=7mm, column sep=1cm,
style me/.style args={##1'##2}{style ##1/.try},
style normal/.style={
draw, minimum width=+3.5cm, minimum height=+1cm, align=center},
style st/.append style={
shape=rectangle, style normal, rounded corners, fill=red!30},
style op/.append style={style st},
style IO/.style={
shape=trapezium, trapezium left angle=70, trapezium right angle=110,
style normal, align=left, fill=blue!30},
style PC/.style={
shape=rectangle, style normal, fill=orange!30},
style if/.style={
shape=diamond, style normal, align=left, fill=green!30, aspect=2},
rl/.style={to path={r-rl(\tikztotarget)\tikztonodes}},
lr around/.style={to path={
-|([xshift=-1cm]##1.west)|-(\tikztotarget)\tikztonodes}},
ortho/rl distance=1cm, ortho/lr distance=3.5cm,
vh/.style={to path={|-(\tikztotarget)\tikztonodes}},
hv/.style={to path={-|(\tikztotarget)\tikztonodes}},
},
STYLE if/.is choice, STYLE if/diamond/.style=,
STYLE if/chamfered/.style={style if/.append style=chamfered rectangle},
STYLE if/labeled/.style={style if/.append style={shape=rectangle, label={
[diamond, draw, fill=white, anchor=center, fill=green!30]north east:}}},
MATRIX/.style={n/.style args={##1'##2}{alias={##1'##2}, style me={##1'##2}}},
GRAPHS/.style={
graphs/every graph/.append style={no placement,
nodes={style me/.expand once=\tikzgraphnodename}},
set text/.code=\def\tikzgraphnodetext{##1},
style st/.append style={set text=Start},
style op/.append style={set text=Stop}},
show node names/.style={style me/.append style={
label={[overlay,node font=\small]north west:##1'##2}}}
}
\begin{document}\ttfamily
\begin{tikzpicture}[>=Latex, COMMON, GRAPHS, STYLE if=labeled]
\graph[/tikz/start chain=down going below] {
{[nodes={on chain=down}]
st'0 -> IO'1 / "Input:\\ f(), a, b, $\varepsilon$"
-> PC'1 / "c=(a+b)/2"
-> if'1 / "if:\\f(a)*f(b) $>$ 0"
->["False"] if'2 / "While:\\f(c) $\not=$ 0 \&\\
\|f(b) - f(a)\| $> \delta$"
->["True"] PC'2 / "c=(a+b)/2"
-> if'3 / "if:\\f(a)*f(c) $<$ 0"
->["False"] PC'3 / "a=c",
IO'2 / "Output:\\H, V, T"
-> PC'4 / "Plot:\\H on T and V on T"[align=left]
-> op'0,
},
if'3 ->["True"] PC'5 / "b=c" [left=of if'3]
->[vh] if'2,
if'2 ->[rl, "False" near start] IO'2,
if'1 ->[hv, "True" above right]
IO'3 / "Output:\\H, V, T" [left=of PC'5.west|-IO'2]
->[vh] op'0,
PC'3 ->[lr around=PC'5] if'2
};
\end{tikzpicture}
\begin{tikzpicture}[>=Triangle, COMMON, MATRIX, STYLE if=chamfered]
\newcommand*\n{\node[name=\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn]}
\matrix[matrix of nodes, nodes={anchor=center}] {
& & |[n=st'0]| Start \\
& & \n[n=IO'1] {Input:\\ f(), a, b, $\varepsilon$}; \\
& & |[n=PC'1]| c=(a+b)/2 \\
& & \n[n=if'1] {if:\\f(a)*f(b) $>$ 0}; \\
& & \n[n=if'2] {While:\\f(c) $\not=$ 0 \&\\
\|f(b) - f(a)\| $> \delta$}; \\
& & |[n=PC'2]| c=(a+b)/2 \\
& |[n=PC'5]| b=c
& \n[n=if'3] {if:\\f(a)*f(c) $<$ 0}; \\
& & |[n=PC'3]| a=c \\
\n[n=IO'3] {Output:\\H, V, T};
& & \n[n=IO'2] {Output:\\H, V, T}; \\
& & \n[n=PC'4, align=left] {Plot:\\H on T and V on T}; \\
& & |[n=op'0]| Stop \\
};
\graph[use existing nodes]{
st'0 -> IO'1
-> PC'1
-> if'1
->["False"] if'2
->["True"] PC'2
-> if'3
->["False"] PC'3
-!- IO'2
-> PC'4
-> op'0,
if'2 ->[rl, "False" near start] IO'2,
if'3 ->["True"] PC'5
->[vh] if'2,
if'1 ->[hv, "True" above right] IO'3
->[vh] op'0,
PC'3 ->[lr around=PC'5] if'2
};
\end{tikzpicture}
\end{document}
Producción
Respuesta3
Su pregunta no me queda del todo clara, pero supongo que está intentando lograr algo como esto (la flecha no se superpone a ningún nodo y se inserta un salto de línea en el nodo verde con forma de diamante en el medio):
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes}
\tikzset{
startstop/.style={
rectangle,
rounded corners,
minimum width=3cm,
minimum height=1cm,
text centered,
draw=black,
fill=red!30
},
io/.style={
trapezium,
trapezium left angle=70,
trapezium right angle=110,
minimum width=3cm,
minimum height=1cm,
text centered,
draw=black,
fill=blue!30
},
process/.style={
rectangle,
minimum width=3cm,
minimum height=1cm,
text centered,
draw=black,
fill=orange!30
},
decision/.style={
diamond,
minimum width=3cm,
minimum height=1cm,
text centered,
align=center, % add
draw=black,
fill=green!30,
},
arrow/.style={
thick,
->,
>=stealth
}
}
\begin{document}
\begin{tikzpicture}[node distance = 1.3cm, auto]
% Place nodes
\node (start) [startstop] {Start};
\node (in1) [io, below of=start] {Input: f(), a, b, $\varepsilon$};
\node (pro1) [process, below of=in1] {c=(a+b)/2};
\node (if1) [decision, below of=pro1, yshift=-1.5cm] {if: f(a)*f(b)$>$0};
% \node (pro1) [process, below of=in1] {Process 1};
\node (dec1) [decision, below of=if1, yshift=-4cm] {While: f(c) $\not=$ 0 \& \\ $|$f(b) - f(a)$|$ $> \delta$};
\node (pro1a) [process, below of=dec1, yshift=-3cm] {c=(a+b)/2};
\node (dec2) [decision, below of=pro1a, yshift=-1.75cm] {if: f(a)*f(c) $<$ 0};
\node (pro2) [process, left of=dec2, xshift=-3cm] {b=c};
\node (pro3) [process, below of=dec2, yshift=-1.5cm] {a=c};
\node (out1) [io, below of=pro3] {Output: H, V, T};
\node (out2) [io, left of=out1, xshift=-4.5cm] {Output: H, V, T};
\node (pro4) [process, below of=out1] {Plot: H on T and V on T};
\node (stop) [startstop, below of=pro4] {Stop};
\draw [arrow] (start) -- (in1);
\draw [arrow] (in1) -- (pro1);
\draw [arrow] (pro1) -- (if1);
\draw [arrow] (if1) -- node {False} (dec1);
\draw [arrow] (dec1) -- node {True} (pro1a);
\draw [arrow] (pro1a) -- (dec2);
\draw [arrow] (dec2) -- node {False} (pro3);
%\draw [arrow] (if1) -- ++(-5.5,-0) -- ++(-1.5,0) |- node [below right] {True} (out2)
\draw [arrow] (if1) -| node [above right] {True} ([xshift=-1cm]out2.north); % replace to coordinate
\draw [arrow] (pro2) |- (dec1.190); % repplace to coordinate
\draw [arrow] (pro3) -- ++(-3.5,-0) -- ++(-2.5,0) |- (dec1.170); % repplace to coordinate
\draw [arrow] (dec2) -- node {True} (pro2);
\draw [arrow] (dec1) -- ++(2.5,-0) -- ++(3,0) |- node [right] {False} (out1);
\draw [arrow] (out1) -- (pro4);
\draw [arrow] ([xshift=-1cm]out2.south) |- (stop); % replace from coordinate
\draw [arrow] (pro4) -- (stop);
\end{tikzpicture}
\end{document}
Espero que esto se acerque un poco a lo que desea lograr y al menos pueda ayudarlo a comenzar. Lo ajusté node distance
un poco para que pareciera menos estrecho.
Permítanme agregar una breve explicación sobre los ajustes relevantes:
- Agregar la opción
align=center
a un nodo le permite agregar saltos de línea usando una doble barra invertida (\) dentro del texto del nodo. - Puede utilizar los anclajes
<node>.north
y<node>.south
para referirse a la parte superior e inferior de un nodo. Además, puede agregar[xshift=<dim>]
una coordenada para desplazarla hacia la izquierda o hacia la derecha o[yshift=<dim>]
hacia arriba o hacia abajo. Por lo tanto, puede, por ejemplo, desplazar la flecha de la izquierda reemplazando el nombre del nodoout2
por la coordenada desplazada del ancla relevante usando[xshift=-1cm]out2.north
y[xshift=-1cm]out2.north
respectivamente. - Un método alternativo es utilizar los llamados anclajes de borde, que están dispuestos en sentido antihorario comenzando desde el lado derecho del nodo y se dan en grados. Por lo tanto, el ancla
<node>.90
normalmente se ubicaría en la misma posición que<node>.north
, pero también puedes usar otros valores además de90
. Utilicé este enfoque para agregar una distancia entre las dos flechas que apuntan al nodo del diamante verde en el medio.