Si compilo el siguiente 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}
No tengo ningún problema y esto me da lo que quiero. Pero la expresión entre "$" no está entre paréntesis.
Si reemplazo $(\i+(0.7,0.7)$
por $\i+(0.7,0.7)$
tengo el siguiente mensaje de error:
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
Y si reemplazo $(\i+(0.7,0.7)$
por $(\i+(0.7,0.7))$
o $(\i)+(0.7,0.7)$
tengo el siguiente mensaje de error:
! 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)$); }
¿Es un error o hago algo mal? (¿O es simplemente una sintaxis extraña y correcta?)
Respuesta1
En el ejemplo dado por el OP,
\fill[lightgray] \i rectangle ($(\i+(0.7,0.7)$);
podría (y probablemente debería) ser
\fill[lightgray] \i rectangle ++(0.7,0.7);
Sin embargo, suponiendo que se trate de un MWE y que la aplicación real requiera inevitablemente el uso de la calc
biblioteca, esto es (como ya se ha señalado) un problema de expansión. Dado que calc
se utiliza la biblioteca, lo siguiente puede ser adecuado:
\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}
A pesar de
\fill let \p1=\i in [lightgray] (\p1) rectangle (\x1+.7, \y1+.7);
sería (creo) marginalmente más eficiente.
Pero si quieres vivir al límite, ponte
\makeatletter
\def\pgffor@scanround(#1)#2,{\def\pgffor@value{#1#2}\pgffor@scanned}
en su preámbulo. Luego ($(\i)+(0.7,0.7)$)
se puede usar dentro del bucle foreach.
Respuesta2
Creo que esto es un engaño de esto.Usando matemáticas en TikZEn pocas palabras, es una interacción extraña que necesita un paréntesis de apertura explícito (por lo tanto, completamente expandido) para obtener el contexto correcto y utiliza el paréntesis de cierre de \i
para finalizar la sintaxis correctamente. Si ve otro, tropieza. La forma correcta es centrar todo en su propio contexto y ser bastante {}
detallado.
Aquí hay una mejor manera de ver lo que está sucediendo con una buena demostración de cómo TeX y TikZ se comunican sobre el análisis de tokens (aunque muy poco intuitivo). Observe los padres que faltan en ciertos lugares, incluida la lista.
La razón principal de tales cosas es que TikZ se bifurca al investigar cuál es el siguiente carácter que se encuentra en la transmisión. Entonces, si se bifurca en un lugar equivocado y luego coloca los términos correctos, no puede regresar y bifurcarse correctamente. No creo que en este tipo de programación puedas eliminar todas estas cosas.
\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}
Respuesta3
Por si sirve de algo, el siguiente código, que no tiene llaves adicionales y está configurado con paréntesis que coinciden correctamente, se compila y proporciona el 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}
Respuesta4
Todas las soluciones anteriores son perfectas. Algunos de ellos explican por qué calc se estropea en su código. Algunos de ellos explican qué debes cambiar para poder usar foreach
el que corre por "puntos" (x_i,y_i)
.
En mi opinión, estás foreach
"equivocado" en el espíritu de TikZ:
- cuando dices
\coordinate (A) at (x,y);
entoncesA
representax,y
y no(x,y)
y lo usas como(A)
. - cuando dices
let \p1=(x,y)
entonces\p1
representax,y
y no(x,y)
y lo usas como(\p1)
.
Así que creo que cuando queramos llegar a foreach
esos puntos deberíamos hacer
\foreach \i in {{x_1,y_1},...,{x_n,y_n}}
y luego usarlo como (\i)
.
En su caso esto se convierte en:
\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}