Wenn ich den folgenden Code kompiliere:
\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}
Ich habe kein Problem und das gibt mir, was ich will. Aber der Ausdruck zwischen "$" ist falsch eingeklammert.
Wenn ich $(\i+(0.7,0.7)$
durch ersetze $\i+(0.7,0.7)$
erhalte ich folgende Fehlermeldung:
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
Und wenn ich $(\i+(0.7,0.7)$
durch $(\i+(0.7,0.7))$
oder ersetze $(\i)+(0.7,0.7)$
, erhalte ich die folgende Fehlermeldung:
! 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)$); }
Ist das ein Fehler oder mache ich etwas falsch? (Oder ist es einfach nur eine korrekte, seltsame Syntax?)
Antwort1
In dem vom OP angeführten Beispiel
\fill[lightgray] \i rectangle ($(\i+(0.7,0.7)$);
könnte (und sollte wahrscheinlich) sein
\fill[lightgray] \i rectangle ++(0.7,0.7);
Wenn jedoch davon ausgegangen wird, dass es sich um ein MWE handelt und die tatsächliche Anwendung die Verwendung der calc
Bibliothek unumgänglich erfordert, handelt es sich (wie bereits erwähnt) um ein Erweiterungsproblem. Da die calc
Bibliothek verwendet wird, könnte Folgendes geeignet sein:
\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}
Obwohl
\fill let \p1=\i in [lightgray] (\p1) rectangle (\x1+.7, \y1+.7);
wäre (glaube ich) geringfügig effizienter.
Aber wenn Sie am Limit leben wollen, setzen Sie
\makeatletter
\def\pgffor@scanround(#1)#2,{\def\pgffor@value{#1#2}\pgffor@scanned}
in Ihrer Präambel. Dann ($(\i)+(0.7,0.7)$)
kann es innerhalb der foreach-Schleife verwendet werden.
Antwort2
Ich denke, das ist eine Duplizierung von diesemMathematik in TikZ verwendenKurz gesagt handelt es sich um eine seltsame Interaktion, die eine explizite (und daher vollständig erweiterte) öffnende Klammer benötigt, um den Kontext richtig darzustellen, und die schließende Klammer verwendet, um \i
die Syntax korrekt abzuschließen. Wenn sie eine andere sieht, stolpert sie. Der richtige Weg besteht darin, alles in seinem eigenen Kontext einzuklammern und ziemlich {}
ausführlich zu sein.
Hier können Sie besser sehen, was passiert, und zwar anhand einer netten Demonstration, wie TeX und TikZ über das Parsen von Token kommunizieren (obwohl dies höchst unintuitiv ist). Beachten Sie die fehlenden Klammern an bestimmten Stellen, einschließlich der Liste.
Der Hauptgrund für solche Dinge ist, dass TikZ verzweigt, indem es untersucht, welches Zeichen als nächstes im Stream gefunden wird. Wenn Sie also an eine falsche Stelle verzweigen und anschließend die richtigen Begriffe eingeben, kann es nicht zurückgehen und richtig verzweigen. Ich glaube nicht, dass Sie bei dieser Art der Programmierung all diese Dinge vermeiden können.
\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}
Antwort3
Der folgende Code, der keine zusätzlichen Klammern enthält und mit korrekt angeordneten Klammern aufgebaut ist, lässt sich kompilieren und liefert das erwartete Ergebnis:
\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}
Antwort4
Alle vorherigen Lösungen sind perfekt. Einige davon erklären, warum calc in Ihrem Code Fehler macht. Einige davon erklären, was Sie ändern sollten, um foreach
das verwenden zu können, was durch „Punkte“ läuft (x_i,y_i)
.
Meiner Meinung nach foreach
ist Ihr „falsch“ im Sinne von TikZ:
- wenn Sie sagen,
\coordinate (A) at (x,y);
dannA
stellen Siex,y
und nicht dar(x,y)
und Sie verwenden es als(A)
. - wenn Sie sagen,
let \p1=(x,y)
dann\p1
stellen Siex,y
und nicht dar(x,y)
und Sie verwenden es als(\p1)
.
Ich denke also, wenn wir foreach
diesen Durchlauf durch Punkte machen wollen, sollten wir
\foreach \i in {{x_1,y_1},...,{x_n,y_n}}
und verwenden Sie es dann als (\i)
.
In Ihrem Fall wird daraus:
\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}