我尝试if
在我的 TikZ 图片中使用。例如,我只想在原点处绘制一个点1 < 2。例如,我可以这样做:
\begin{tikzpicture}
if 1 < 2 then
\fill (0, 0) circle (1pt);
\end{tikzpicture}
这段代码可以正常工作。但如果我尝试if
在循环中使用,那么一切都会停止工作。例如,以下代码将绘制 5 个点,而不是 1 个
\begin{tikzpicture}
\foreach \i in {1, ..., 5}
if \i < 2 then
\fill (\i, 0) circle (1pt);
\end{tikzpicture}
我做错了什么以及如何使代码正常工作?
我在网上唯一能找到的是这个答案,据此可以实现如下期望,但是代码太过繁琐。
\begin{tikzpicture}
\foreach \i in {1, ..., 5} {
\pgfmathparse{ifthenelse(\i<2, 1, 0)}
\ifodd\pgfmathresult\relax
\fill (\i, 0) circle (1pt);
\fi
}
\end{tikzpicture}
答案1
该包ifthen
具有最自然的语法(在我看来)。
\ifthenelse{<boolean>}{<do this if true>}{<do this if false>}
请注意,要使用\foreach
,必须将循环括在括号中,除非它是单个 tikz 命令(例如\draw
)。
\documentclass{article}
\usepackage{tikz,ifthen}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1, ..., 5}{
\ifthenelse{\i < 3}{\fill (\i, 0) circle (1pt);}{}
}
\end{tikzpicture}
\end{document}
答案2
我可以提供一组更灵活的功能,请参阅https://tex.stackexchange.com/a/467527/4427
\documentclass{article}
\usepackage{tikz}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\xifthenelse}{mmm}
{
\bool_if:nTF { #1 } { #2 } { #3 }
}
\cs_new_eq:NN \numtest \int_compare_p:n
\cs_new_eq:NN \oddtest \int_if_odd_p:n
\cs_new_eq:NN \fptest \fp_compare_p:n
\cs_new_eq:NN \dimtest \dim_compare_p:n
\cs_new_eq:NN \deftest \cs_if_exist_p:N
\cs_new_eq:NN \namedeftest \cs_if_exist_p:c
\cs_new_eq:NN \eqdeftest \token_if_eq_meaning_p:NN
\cs_new_eq:NN \streqtest \str_if_eq_p:ee
\cs_new_eq:NN \emptytest \tl_if_empty_p:n
\cs_new_eq:NN \blanktest \tl_if_blank_p:n
\cs_new_eq:NN \boolean \legacy_if_p:n
\cs_new:Npn \modetest #1
{
\str_case:nnF { #1 }
{
{h}{\mode_if_horizontal_p:}
{v}{\mode_if_vertical_p:}
{m}{\mode_if_math_p:}
{i}{\mode_if_inner_p:}
}
{\c_false_bool}
}
\cs_new:Npn \enginetest #1
{
\str_case:nnF { #1 }
{
{luatex}{\sys_if_engine_luatex_p:}
{pdftex}{\sys_if_engine_pdftex_p:}
{ptex}{\sys_if_engine_ptex_p:}
{uptex}{\sys_if_engine_uptex_p:}
{xetex}{\sys_if_engine_xetex_p:}
}
{\c_false_bool}
}
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\foreach \i in {1,...,8}{
\xifthenelse{\numtest{ 2 <= \i < 5 }}
{
\fill (\i, 0) circle (1pt);
}
{
\draw (\i, 0) circle (1pt);
}
}
\foreach \i in {1,...,8}{
\xifthenelse{ \numtest{ 3 < \i < 6 } || \numtest{ \i>7 } }
{
\fill (\i, 1) circle (1pt);
}
{
\draw (\i, 1) circle (1pt);
}
}
\end{tikzpicture}
\end{document}
答案3
请尝试以下操作:
\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1, ..., 5}
{ % <---
\ifnum \i < 3 % <---
\fill (\i, 0) circle (1pt);
\fi % <---
} % <---
\end{tikzpicture}
\end{document}
或者
\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1, ..., 5}
{
\ifnum \i < 3
\fill (\i, 0) circle (1pt);
\else
\draw (\i, 0) circle (1pt);
\fi
}
\end{tikzpicture}
\end{document}
答案4
请注意 OP 代码中的 TikZ
\begin{tikzpicture}
if 1 < 2 then
\fill (0, 0) circle (1pt);
\end{tikzpicture}
TikZ 会忽略它,if 1 < 2 then
因为它是错误的语法;事实上,如果你写逆不等式if 1 > 2 then
,那么代码仍然可以使用相同的输出。TikZ 会忽略一些错误的语法错误。但 Asymptote 的情况并非如此。
我觉得这个问题很有趣。我将分享一些关于使用 TikZ 编程/绘图的个人感受,并与 Asymptote 进行比较。让我们从代码示例开始手册,第 88 节重复事物:Foreach 语句。
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \x in {1,...,4}
\foreach \y in {1,...,4}
{
\fill[red!50] (\x,\y) ellipse (3pt and 6pt);
\ifnum \x<\y
\breakforeach
\fi
}
\end{tikzpicture}
\hspace*{5mm}
\begin{tikzpicture}
\foreach \x in {1,...,4}
\foreach \y in {1,...,4}
{
\ifnum \x>\y
\fill[blue!50] (\x,\y) ellipse (3pt and 6pt);
\fi
\ifnum \x=\y
\fill[cyan!50] (\x,\y) ellipse (3pt and 6pt);
\fi
\pgfmathparse{\y-1}
\ifnum \x=\pgfmathresult
\fill[magenta!50] (\x,\y) ellipse (3pt and 6pt);
\fi
}
\end{tikzpicture}
\hspace*{5mm}
\begin{tikzpicture}
\foreach \x in {1,...,4}
\foreach \y in {1,...,4}
{
\pgfmathparse{\x>=\y-1}
\ifnum \pgfmathresult=1
\fill[violet!50] (\x,\y) ellipse (3pt and 6pt);
\fi
}
\end{tikzpicture}
\end{document}
附录
// http://asymptote.ualberta.ca/
unitsize(1cm);
int n=5;
for(int i=1;i<n;++i)
for(int j=1;j<n;++j)
if (i>=j-1) fill(ellipse((i,j),3pt/cm,6pt/cm),orange);
(待续)