
Eu tenho dois diagramas (ambos devem ser iguais), um com comandos explícitos de desenho e nó, o outro com foreach
loops. Obviamente, não entendo os loops foreach, pois só consigo fazer um funcionar. Segui o tutorial do tikz, mas rapidamente passou pela minha cabeça. Estou tentando entender a lógica do tikz por tentativa e erro, mas fiquei um pouco desanimado depois de tentar coisas aparentemente simples. Preciso de ajuda com os outros. Peço um empurrãozinho na direção certa sobre como devo fazer isso. Como eu precisaria projetar meus loops para encurtar o código do primeiro diagrama. O segundo não funciona quando as linhas são comentadas.
\documentclass{article}
\usepackage[margin=20mm]{geometry}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) rectangle +(10.5,8);
\draw (0.1,0.1) rectangle +(10.3,7.8);
\foreach \x in {1.5,4,6.5,9}
\foreach \y in {1.5,4,6.5}
\draw (\x,\y) circle (1);
\node at (1.5,1.5) {PreA30};
\node at (1.5,4) {PreB30};
\node at (1.5,6.5) {PreC30};
\node at (4,1.5) {PreA50};
\node at (4,4) {PreB50};
\node at (4,6.5) {PreC50};
\node at (6.5,1.5) {PreA70};
\node at (6.5,4) {PreB70};
\node at (6.5,6.5) {PreC70};
\node at (9,1.5) {PreA90};
\node at (9,4) {PreB90};
\node at (9,6.5) {PreC90};
\node at (1.5,-.5) {30\%};
\node at (4,-.5) {50\%};
\node at (6.5,-.5) {70\%};
\node at (9,-.5) {90\%};
\node at (-.5,1.5) {A};
\node at (-.5,4) {B};
\node at (-.5,6.5) {C};
\end{tikzpicture}
\begin{tikzpicture}
\draw (0,0) rectangle +(10.5,8);
\draw (0.1,0.1) rectangle +(10.3,7.8);
\foreach \x in {1.5,4,6.5,9}
\foreach \y in {1.5,4,6.5}
\draw (\x,\y) circle (1);
% the next block actually compiles, but the result is quite alarming
% I tried a different order, but that doesn't seem to matter at all
%\foreach \x in {1.5,4,6.5,9}
% \foreach \y in {1.5,4,6.5}
% \foreach \sam in {A,B,C}
% \foreach \perc in {30,50,70,90}
% \node at (\x,\y) {Pre\sam\perc};
%
%\foreach \x in {1.5,4,6.5,9}
% \foreach \perc in {30,50,70,90}
% \node at (\x,-.5) {\perc\%};
%
%\foreach \y in {1.5,4,6.5}
% \foreach \sam in {A,B,C}
% \node at {-.5,\y} {\sam};
\end{tikzpicture}
\end{document}
Com a resposta das marmotas, obtemos o que é mostrado na imagem abaixo. O primeiro diagrama é o que se deseja. O segundo diagrama possui superposições de texto em todos os nós. Eu sei que isso provavelmente tem mais a ver com lógica do que com LaTeX, mas ainda assim, não consigo entender o design correto dos loops for.
Responder1
Você tem quatro loops aninhados, mas deseja apenas dois, mas precisa ter mais de uma variável de loop. Isso pode ser feito com, por exemplo
\foreach \x/\perc in {1.5/30,4/50,6.5/70,9/90}
ou seja, cada item na lista de variáveis contém dois valores, separados por /
.
Em relação ao seu código original, os loops funcionam bem, o único problema é que você usou no \node at {-.5,\y} {\sam};
lugar \node at (-.5,\y) {\sam};
do final. (Chaves em vez de parênteses na coordenada.) Corrigindo o problema de impressão sobreposta, porque para cada par de valores \x
/ \y
, você imprime 12 nós: três letras diferentes (A, B, C) e quatro números diferentes (30, 50 , 70, 90), dê 12 combinações.
\documentclass{article}
\usepackage[margin=20mm]{geometry}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) rectangle +(10.5,8);
\draw (0.1,0.1) rectangle +(10.3,7.8);
\foreach \x in {1.5,4,6.5,9}
\foreach \y in {1.5,4,6.5}
\draw (\x,\y) circle (1);
\node at (1.5,1.5) {PreA30};
\node at (1.5,4) {PreB30};
\node at (1.5,6.5) {PreC30};
\node at (4,1.5) {PreA50};
\node at (4,4) {PreB50};
\node at (4,6.5) {PreC50};
\node at (6.5,1.5) {PreA70};
\node at (6.5,4) {PreB70};
\node at (6.5,6.5) {PreC70};
\node at (9,1.5) {PreA90};
\node at (9,4) {PreB90};
\node at (9,6.5) {PreC90};
\node at (1.5,-.5) {30\%};
\node at (4,-.5) {50\%};
\node at (6.5,-.5) {70\%};
\node at (9,-.5) {90\%};
\node at (-.5,1.5) {A};
\node at (-.5,4) {B};
\node at (-.5,6.5) {C};
\end{tikzpicture}
\begin{tikzpicture}
\draw (0,0) rectangle +(10.5,8);
\draw (0.1,0.1) rectangle +(10.3,7.8);
\foreach \x/\perc in {1.5/30,4/50,6.5/70,9/90}
{ % here you need to use braces, because there is more than one thing in the loop
\node at (\x,-0.5) {\perc\%};
\foreach \y/\sam in {1.5/A,4/B,6.5/C}
{
\draw (\x,\y) circle (1);
\node at (\x,\y) {Pre\sam\perc};
}
}
% second loop for y-labels
\foreach \y/\sam in {1.5/A,4/B,6.5/C}
\node at (-0.5,\y) {\sam};
\end{tikzpicture}
\end{document}
Segunda versão
Existem mais opções disponíveis para \foreach
, conforme descrito no capítulo 83 emo manual. Para um caso como este, com nós espaçados regularmente, pode fazer sentido usar a count
opção, que fornece um contador para a variável de loop. E ainda mais, você pode usar evaluate
para fazer cálculos.
Dessa forma, você pode ter apenas uma variável de loop para cada um dos loops e calcular as coordenadas com base na iteração em que você está no loop. A saída é como acima.
\documentclass{article}
\usepackage[margin=20mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{fit, backgrounds}
\begin{document}
\begin{tikzpicture}
\foreach [count=\i, evaluate={\x=\i*2.5}] \perc in {30,50,70,90}
{ % here you need to use braces, because there is more than one thing in the loop
\foreach [count=\j, evaluate={\y=\j*2.5}] \sam in {A,B,C}
{
\node [circle,draw,minimum size=2cm] (\sam\perc) at (\x,\y) {Pre\sam\perc};
\ifnum \i=1
\node [left=5mm] at (\sam30.west) {\sam};
\fi
} % inner loop ends here
% so this node is only in outer loop
\node [below=5mm] at (A\perc.south) {\perc\%};
}
\begin{scope}[on background layer]
% fit both around same nodes, with different inner sep
\node[draw,fit=(A30)(C90),inner sep=3mm, fill=blue!20] (frame) {}; % outer frame, larger inner sep
\node[draw,fit=(A30)(C90),inner sep=2mm, fill=red!20] (frame) {}; % inner frame, smaller inner sep
\end{scope}
\end{tikzpicture}
\end{document}
Responder2
Eu sei que esta pergunta é sobre foreach
, mas se alguém tiver problemas para entender foreach
o uso, é fácil reproduzir este diagrama com uma matrix
ajuda:
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{positioning, matrix, fit}
\begin{document}
\begin{tikzpicture}
\matrix[matrix of nodes,
nodes={anchor=center,
circle, draw, minimum size=2cm},
column 1/.style={%
nodes={rectangle, minimum size=0pt, draw=none}},
row 4/.style={%
nodes={rectangle, minimum size=0pt, draw=none}},
column sep=5mm, row sep=5mm]
(top)
{
C & PreC30 & PreC50 & PreC70 & PreC90 \\
B & PreB30 & PreB50 & PreB70 & PreB90 \\
A & PreA30 & PreA50 & PreA70 & PreA90 \\
& 30\% & 50\% & 70\% & 90\% \\
};
\node[draw, double, fit=(top-1-2) (top-3-5), inner sep=3mm] {};
\end{tikzpicture}
\end{document}
Responder3
Se você usar os \foreach
loops você precisa colocar tudo que deveria estar dentro do loop em um grupo, ou seja, cercá-lo {
e }
a menos que você tenha apenas um comando/grupo no loop. Aplicando isso ao seu código produz
\documentclass{article}
\usepackage[margin=20mm]{geometry}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) rectangle +(10.5,8);
\draw (0.1,0.1) rectangle +(10.3,7.8);
\foreach \x in {1.5,4,6.5,9}
\foreach \y in {1.5,4,6.5}
\draw (\x,\y) circle (1);
\node at (1.5,1.5) {PreA30};
\node at (1.5,4) {PreB30};
\node at (1.5,6.5) {PreC30};
\node at (4,1.5) {PreA50};
\node at (4,4) {PreB50};
\node at (4,6.5) {PreC50};
\node at (6.5,1.5) {PreA70};
\node at (6.5,4) {PreB70};
\node at (6.5,6.5) {PreC70};
\node at (9,1.5) {PreA90};
\node at (9,4) {PreB90};
\node at (9,6.5) {PreC90};
\node at (1.5,-.5) {30\%};
\node at (4,-.5) {50\%};
\node at (6.5,-.5) {70\%};
\node at (9,-.5) {90\%};
\node at (-.5,1.5) {A};
\node at (-.5,4) {B};
\node at (-.5,6.5) {C};
\end{tikzpicture}
\begin{tikzpicture}
\draw (0,0) rectangle +(10.5,8);
\draw (0.1,0.1) rectangle +(10.3,7.8);
\foreach \x in {1.5,4,6.5,9}
{\foreach \y in {1.5,4,6.5}
\draw (\x,\y) circle (1);}
% the next block actually compiles, but the result is quite alarming
% I tried a different order, but that doesn't seem to matter at all
\foreach \x in {1.5,4,6.5,9}
{\foreach \y in {1.5,4,6.5}
\foreach \sam in {A,B,C}
{\foreach \perc in {30,50,70,90}
\node at (\x,\y) {Pre\sam\perc};}}
\foreach \x in {1.5,4,6.5,9}
{\foreach \perc in {30,50,70,90}
\node at (\x,-.5) {\perc\%};}
\foreach \y in {1.5,4,6.5}
{\foreach \sam in {A,B,C}
\node at (-.5,\y) {\sam};}
\end{tikzpicture}
\end{document}
O código fornece agora o que acho que você queria obter.