Se eu compilar o seguinte código:
\documentclass[12pt]{article}
\usepackage[french]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\foreach \i in {(0,0),(0,2.1),(2.1,2.1),(2.1,0)} {
\fill[lightgray] \i rectangle ($(\i+(0.7,0.7)$); }
\draw (0,0) grid[step=0.7] (2.8,2.8);
\end{tikzpicture}
\end{document}
Não tenho nenhum problema e isso me dá o que eu quero. Mas a expressão entre "$" não está entre parênteses.
Se eu substituir $(\i+(0.7,0.7)$
por, $\i+(0.7,0.7)$
recebo a seguinte mensagem de erro:
Runaway argument?
\i +(0.7,0.7)$); \pgffor@endhook \ifx \pgffor@assign@after@code \pgfutil@empty
\ETC.
! Paragraph ended before \tikz@cc@parse@factor was complete.
<to be read again>
\par
l.15
E se eu substituir $(\i+(0.7,0.7)$
por $(\i+(0.7,0.7))$
ou $(\i)+(0.7,0.7)$
tiver a seguinte mensagem de erro:
! Package tikz Error: + or - expected.
See the tikz package documentation for explanation.
Type H <return> for immediate help.
...
l.12 ...htgray] \i rectangle ($(\i)+(0.7,0.7)$); }
É um bug ou fiz algo errado? (ou é apenas uma sintaxe estranha correta?)
Responder1
No exemplo dado pelo OP,
\fill[lightgray] \i rectangle ($(\i+(0.7,0.7)$);
poderia (e provavelmente deveria) ser
\fill[lightgray] \i rectangle ++(0.7,0.7);
No entanto, assumindo que este é um MWE e a aplicação real requer inevitavelmente o uso da calc
biblioteca, este é (como já foi apontado) um problema de expansão. À medida que a calc
biblioteca está sendo usada, o seguinte pode ser adequado:
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\foreach \i in {(0,0),(0,2.1),(2.1,2.1),(2.1,0)} {
\fill let \p1=\i in [lightgray] (\p1) rectangle ($(\p1)+(0.7,0.7)$); }
\draw (0,0) grid[step=0.7] (2.8,2.8);
\end{tikzpicture}
\end{document}
Embora
\fill let \p1=\i in [lightgray] (\p1) rectangle (\x1+.7, \y1+.7);
seria (eu acho) um pouco mais eficiente.
Mas se você quer viver no limite, coloque
\makeatletter
\def\pgffor@scanround(#1)#2,{\def\pgffor@value{#1#2}\pgffor@scanned}
em seu preâmbulo. Então o ($(\i)+(0.7,0.7)$)
pode ser usado dentro do loop foreach.
Responder2
Eu acho que isso é uma bobagem dissoUsando matemática no TikZResumindo, é uma interação estranha que precisa de um parêntese de abertura explícito (portanto, totalmente expandido) para acertar o contexto e usa o parêntese de fechamento \i
para finalizar a sintaxe corretamente. Se vir outro tropeça. A maneira correta é colocar tudo em seu próprio contexto e ser bastante {}
detalhado.
Aqui está uma maneira melhor de ver o que está acontecendo com uma boa demonstração de como o TeX e o TikZ se comunicam sobre a análise de tokens (embora altamente não intuitivo). Observe os parênteses ausentes em alguns lugares, incluindo a lista.
A principal razão para tais coisas é que o TikZ se ramifica investigando qual o próximo caractere encontrado no stream. Portanto, se você ramificar para um lugar errado e colocar os termos corretos depois, ele não poderá voltar e ramificar corretamente. Não creio que neste tipo de programação você possa eliminar todas essas coisas.
\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\foreach \i in {{(0,0},{(0,2.1},{(2.1,2.1},{(2.1,0}} {
\fill[lightgray] \i) rectangle ($(\i)+(0.7,0.7)$); }
\draw (0,0) grid[step=0.7] (2.8,2.8);
\end{tikzpicture}
\end{document}
Responder3
Pelo que vale, o código a seguir, que não possui colchetes extras e é configurado com parênteses correspondentes corretamente, compila e fornece o resultado esperado:
\documentclass[12pt]{article}
\usepackage[french]{babel}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xinttools}
\begin{document}
% \begin{tikzpicture}
% \foreach \i in {(0,0),(0,2.1),(2.1,2.1),(2.1,0)} {
% \fill[lightgray] \i rectangle ($(\i+(0.7,0.7)$); }
% \draw (0,0) grid[step=0.7] (2.8,2.8);
% \end{tikzpicture}
\begin{tikzpicture}
\xintForpair #1#2 in {(0,0),(0,2.1),(2.1,2.1),(2.1,0)} \do {
\fill[lightgray] (#1,#2) rectangle ($(#1,#2)+(0.7,0.7)$); }
\draw (0,0) grid[step=0.7] (2.8,2.8);
\end{tikzpicture}
\end{document}
Responder4
Todas as soluções anteriores são perfeitas. Alguns deles explicam por que o calc atrapalha seu código. Alguns deles explicam o que você deve alterar para poder usar foreach
o que passa por "pontos" (x_i,y_i)
.
Na minha opinião, você foreach
está "errado" no espírito do TikZ:
- quando você diz
\coordinate (A) at (x,y);
entãoA
representax,y
e não(x,y)
e você usa como(A)
. - quando você diz
let \p1=(x,y)
então\p1
representax,y
e não(x,y)
e você usa como(\p1)
.
Então eu acho que quando quisermos fazer foreach
essa análise dos pontos, deveríamos fazer
\foreach \i in {{x_1,y_1},...,{x_n,y_n}}
e então use-o como (\i)
.
No seu caso, isso se torna:
\documentclass[tikz,varwidth,border=5]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\foreach \i in {{0,0},{0,2.1},{2.1,2.1},{2.1,0}}
\fill[lightgray] (\i) rectangle ($(\i)+(0.7,0.7)$);
\draw (0,0) grid[step=0.7] (2.8,2.8);
\end{tikzpicture}
\end{document}