我想创建一系列显示菱形折叠的图像。我可以做我想做的事,但代码不太优雅。我最终(不必要地)重复了一大堆代码来获得我想要的效果。
代码如下:
\documentclass{article}
\usepackage[svgnames]{xcolor}
\usepackage[margin=0.35in]{geometry}
\usepackage{tikz}
\usepackage{tkz-euclide}
\usetikzlibrary{calc}
\usetikzlibrary{decorations}
\tikzset{rhombus fill/.style={fill=blue!\number\numexpr30+#1\relax},
my arrow/.style={decorate,decoration={markings,mark=at position 1 with {\arrow[scale=2.25]{stealth};}}}}
\def\mystep{6}
\edef\myangle{0}
\def\stepmyangle#1{\xdef\myangle{\number\numexpr\myangle+#1\relax}}
\pagestyle{empty}
\setlength{\parindent}{0pt}
\begin{document}
%-@-(4)------------------------------------------------------------------------------------
\newcounter{currentstep}
\foreach \x/\y in {0/0,10/30,12/60,14/0,10/0,9/0}
{\stepmyangle{\x}%%
\begin{tikzpicture}
\coordinate (W) at (0,2in);
\coordinate (Y) at (0,-2in);
\coordinate (X) at (1.14in,0);
\coordinate (Z) at (-1.14in,0);
\fill[rhombus fill=0] (W) -- (Z) -- (Y);
\ifnum\x>0\relax
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in
coordinate (A) at ($(W)+(\n3-\myangle:\n2)$);
\fill[rhombus fill=\y] (W) -- (A) -- (Y);
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in
coordinate (A) at ($(W)+(\n3-\myangle:\n2)$)
%% Here results in an error message: "Missing \endcsname insert"
%%[fill,rhombus fill=\y] (W) -- (A) -- (Y)
[draw,postaction={my arrow}] (A) arc (\n3-\myangle:\n1:\n2)
;
\else
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in
coordinate (A) at ($(W)+(\n3:\n2)$)
;
\fi
%% Here doesn't work because it blocks the arrows.
%%[fill,rhombus fill=\y] (W) -- (A) -- (Y)
\draw[gray!20] (W) -- (X) -- (Y);
\draw (W)
\foreach \x in {A,Y,Z} { -- (\x) } -- cycle;
\draw[dashed] (W) -- (Y);
\ifnum\thecurrentstep>2\relax\draw[black,fill=black!20] (W) -- (A) -- (Y) -- cycle;\fi
\end{tikzpicture}%%
\ifnum\thecurrentstep=2\relax
\vspace{2ex}\par
\else
\ifnum\thecurrentstep<5\relax
\hspace*{\fill}%%
\fi
\fi
\global\stepcounter{currentstep}%%
}
\end{document}
生成结果:
这第一的问题是我重复了一段代码:
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in ...;
如果我可以设置这些值一次,然后在需要时从路径外部调用它们,那就太好了。我尝试过类似
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in \edef\myarclength{\n2};
但这导致了错误。
这第二问题是我似乎不能只写
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in
coordinate (A) at ($(W)+(\n3-\myangle:\n2)$)
[fill,rhombus fill=\y] (W) -- (A) -- (Y)
[draw,postaction={my arrow}] (A) arc (\n3-\myangle:\n1:\n2)
;
并节省了我重新粘贴代码的时间。最后一个例子的结果是
Missing \endcsname insert
错误信息。
答案1
第二个问题出现是因为你同时使用了\y
变量\foreach
和calc
的简写形式是坐标值\p
。
\foreach \xValue/\yValue in …
当您使用时使用即可解决这个问题rhombus fill=\yValue
。
第一个问题稍微复杂一点。你实际上可以在路径上执行任意 TeX 操作。你可以使用
\path \pgfextra{<TeX stuff>};
\path \pgfextra<TeX stuff>\endpgfextra;
或者
\path [/utils/exec=<TeX stuff>];
% or /utils/exec={<TeX stuff>} if <TeX stuff> contains , or =
\def
但是用/定义的宏\edef
只会在该路径上定义,并且不会在 中保留;
。您需要在这里使用\gdef
/ \xdef
。(我不知道您想在哪里使用,\myarclength
所以我不能说是否有其他方法可以解决这个问题。)
但我看到了第三个问题:
你不能 draw
路径的一部分和fill
路径的另一部分(我敢说!弧也会有填充……)。
不过,在您的情况下,您可以保存坐标(A)
并绘制圆弧,然后使用\fill
已保存坐标的三角形的另一部分(A)
。
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in [draw, postaction=my arrow]
($(W)+(\n3-\myangle:\n2)$) coordinate (A) arc (\n3-\myangle:\n1:\n2);
\fill[rhombus fill=\yValue] (W) -- (A) -- (Y);
我意识到这没有帮助,因为您首先要填充该区域,然后绘制箭头(保存值以供日后使用会很方便\n
)。
幸运的是,你能 draw
和fill
路径的各个部分分别;实际上,edge
路径运算符创建了另一条路径,但我们可以使用它:
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in
(W) edge [rhombus fill=\yValue,
to path={--($(W)+(\n3-\myangle:\n2)$) coordinate (A)--(Y)}] ()
(A) edge [draw, postaction=my arrow,
to path={arc (\n3-\myangle:\n1:\n2)}] ();
是的,我们只是忽略\tikztotarget
并直接在中指定我们的路径to path
。
如果你看一下新的循环头:
\foreach \xValue/\yValue[
evaluate={\myangle=\myangle+\xValue},
remember=\myangle as \myangle (initially 0),
count=\currentstep from 0] in {0/0, 10/30, 12/60, 14/0, 10/0, 9/0}{
我已将您的计数器和辅助宏纳入\foreach
选项中。
此外,您也许可以尝试用一张(因此只有一张 TikZ 图片)来绘制图表\matrix
,但我想这不再属于这个问题了。
代码
\documentclass{article}
\usepackage[svgnames]{xcolor}
\usepackage[margin=0.35in]{geometry}
\usepackage{tikz,tkz-euclide}
\usetikzlibrary{calc,decorations}
\tikzset{
rhombus fill/.style={fill=blue!\number\numexpr30+#1\relax},
my arrow/.style={
decorate,
decoration={markings,mark=at position 1 with {\arrow[scale=2.25]{stealth};}}}}
\begin{document}
\foreach \xValue/\yValue[
evaluate={\myangle=\myangle+\xValue},
remember=\myangle as \myangle (initially 0),
count=\currentstep from 0] in {0/0, 10/30, 12/60, 14/0, 10/0, 9/0}{
\begin{tikzpicture}
\coordinate (W) at (0,2in);
\coordinate (Y) at (0,-2in);
\coordinate (X) at (1.14in,0);
\coordinate (Z) at (-1.14in,0);
\fill[rhombus fill=0] (W) -- (Z) -- (Y);
\ifnum\xValue>0\relax
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in
(W) edge [rhombus fill=\yValue,
to path={-- ($(W)+(\n3-\myangle:\n2)$) coordinate (A) -- (Y)}] ()
(A) edge [draw, postaction=my arrow,
to path={arc (\n3-\myangle:\n1:\n2)}] ();
\else
\path let
\p1=($(Y)-(X)$),
\n1={atan2(\y1,\x1)},
\n2={veclen(\y1,\x1)},
\p2=($(Y)-(Z)$),
\n3={atan2(\y2,\x2)}
in coordinate (A) at ($(W)+(\n3:\n2)$);
\fi
\draw[gray!20] (W) -- (X) -- (Y);
\draw (W) \foreach \x in {A,Y,Z} { -- (\x) } -- cycle;
\draw[dashed] (W) -- (Y);
\ifnum\currentstep>2\relax\draw[black,fill=black!20] (W) -- (A) -- (Y) -- cycle;\fi
\end{tikzpicture}%
\ifnum\currentstep=2\relax
\vspace{2ex}\par
\else
\ifnum\currentstep<5\relax
\hspace*{\fill}%%
\fi
\fi}
\end{document}