如果我編譯以下程式碼:
\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}
我沒有問題,這給了我我想要的。但「$」之間的表達式沒有括號。
如果我替換$(\i+(0.7,0.7)$
為$\i+(0.7,0.7)$
我有以下錯誤訊息:
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
如果我替換$(\i+(0.7,0.7)$
為$(\i+(0.7,0.7))$
or$(\i)+(0.7,0.7)$
我有以下錯誤訊息:
! 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)$); }
這是一個錯誤還是我做錯了什麼? (或者這只是一個正確的奇怪語法?)
答案1
在OP所給的例子中,
\fill[lightgray] \i rectangle ($(\i+(0.7,0.7)$);
可以(並且可能應該)是
\fill[lightgray] \i rectangle ++(0.7,0.7);
然而,假設這是一個 MWE 並且實際應用程式不可避免地需要使用該calc
庫,這是(正如已經指出的)擴展問題。由於calc
正在使用該庫,以下內容可能適合:
\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}
雖然
\fill let \p1=\i in [lightgray] (\p1) rectangle (\x1+.7, \y1+.7);
(我認為)會稍微更有效率。
但如果你想生活在邊緣,那就把
\makeatletter
\def\pgffor@scanround(#1)#2,{\def\pgffor@value{#1#2}\pgffor@scanned}
在你的序言中。然後($(\i)+(0.7,0.7)$)
可以在 foreach 迴圈中使用。
答案2
我認為這是一個騙局在 TikZ 中使用數學長話短說,這是一種奇怪的交互,它需要一個顯式的(因此完全擴展的)左括號來獲得正確的上下文,並使用右括號來\i
正確地完成語法。如果它看到另一個人絆倒。正確的方法是將所有內容放在各自的上下文中,並且非常{}
冗長。
這是一種更好的方式來了解正在發生的情況,很好地演示了 TeX 和 TikZ 如何在解析令牌方面進行通訊(儘管非常不直觀)。請注意某些地方缺少括號,包括清單。
造成這種情況的主要原因是 TikZ 透過調查在流中找到下一個字元來進行分支。因此,如果您分支到錯誤的位置並隨後輸入正確的術語,則它無法返回並正確分支。我不認為在這種類型的程式設計中你可以消除所有這些東西。
\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}
答案3
無論如何,以下程式碼沒有額外的大括號,並且使用正確匹配的括號進行設置,可以編譯並給出預期結果:
\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}
答案4
之前的所有解決方案都是完美的。其中一些解釋了為什麼 calc 在程式碼中會出現混亂。其中一些解釋了您應該更改哪些內容才能使用foreach
貫穿“點”的內容(x_i,y_i)
。
在我看來,你的foreach
TikZ 精神是「錯誤的」:
- 當你說
\coordinate (A) at (x,y);
thenA
代表x,y
而不是 時(x,y)
,你將它用作(A)
。 - 當你說
let \p1=(x,y)
then\p1
代表x,y
而不是 時(x,y)
,你將它用作(\p1)
。
所以我認為當我們想要達到foreach
最低點時我們應該這樣做
\foreach \i in {{x_1,y_1},...,{x_n,y_n}}
然後將其用作(\i)
.
在你的情況下,這變成:
\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}