笔记:我刚刚意识到这个问题的答案可能对我没有帮助——我已经忘记了这个问题在 tikz 的“to”路径中设置“in”,而不是“out”,这有点让它变得毫无意义——无论如何,我可能必须分别考虑每个组合。不过,对“如何\newcommand
在 TikZ 路径的选项内扩展”这个一般问题的回答可能对其他人仍然有帮助。
我想创建一个输出 tikz 路径选项的命令。在下面的 MWE 中,宏\pathoptions
始终输出out=0
,但在我的实际代码中,其输出将根据用户输入而变化。以下代码失败:
\documentclass{article}
\usepackage{tikz}
\newcommand{\pathoptions}{
out=0
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) to[\pathoptions] (1,1);
\end{tikzpicture}
\end{document}
错误是
./tikz_path_options.tex:12: Package pgfkeys Error: I do not know the key '/tikz
/ out=0 ' and I am going to ignore it. Perhaps you misspelled it.
因此它似乎将“out=0”视为键的名称,而不是将键“out”设置为值“0”。我该如何解决这个问题?
这可能是一个 XY 问题,所以我会先说一下我想要实现的目标。这个想法是,有时\pathoptions
宏会输出out=0
,有时in=180
,有时两者都输出,有时两者都不输出。
因此,理想的效果是,根据用户输入,路径的任一或两个端点可能有固定方向,也可能没有。这正是我真正想要实现的,如果有其他方法可以实现此结果,我很乐意听到。
不过,我更愿意避免单独考虑这四种组合([out=0,in=180]
、[out=0]
和),因为如果我添加其他键[in=180]
,[]
组合的数量将呈指数增长。
答案1
我不确定是否理解了你的问题,但是你为什么不使用 TikZ 样式?
\documentclass{article}
\usepackage{tikz}
\tikzset{
styleA/.style={
out=0,in=180
},
styleB/.style={
out=0
},
styleC/.style={
in=180
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) to[styleA] (1,1);
\draw (0,-1) to[styleB] (1,0);
\draw (0,-2) to[styleC] (1,-1);
\draw (0,-3) to[] (1,-2);
\end{tikzpicture}
\end{document}
编辑
带有参数:
\documentclass{article}
\usepackage{tikz}
\newcommand{\pathoptions}[1]{\tikzset{mystyle/.style={#1}}}
\begin{document}
\pathoptions{out=0,in=180}
\begin{tikzpicture}
\draw (0,0) to[mystyle] (1,1);
\end{tikzpicture}
\pathoptions{out=0}
\begin{tikzpicture}
\draw (0,0) to[mystyle] (1,1);
\end{tikzpicture}
\pathoptions{in=180}
\begin{tikzpicture}
\draw (0,0) to[mystyle] (1,1);
\end{tikzpicture}
\pathoptions{}
\begin{tikzpicture}
\draw (0,0) to[mystyle] (1,1);
\end{tikzpicture}
\end{document}
答案2
我将展示两种解决方案:
第一个只使用 TikZ/PGFkeys,借助
/utils/if={<cond>}{<true kv>}{<false kv>}
测试<cond>
并应用<true kv>
的密钥<false kv>
的- 调用一个 PGFmath 函数,当处于时
instr("<sub>","<text>")
返回1
(true) ,否则返回 (false)。<sub>
<text>
0
第二种解决方案使用使用
check outin xstring={<start>}{<target>}
并通过应用所需的样式。xstring
\IfSubStr
\pgfkeysalso
在 的选项中to
,您可以访问路径的起点和目标,以及\tikztostart
我\tikztotarget
在第一个解决方案中使用的路径。这不适用于 这edge
就是为什么check outin xstring
需要两个参数。
显然,第一个解决方案的风格也可以定义为
check outin/.style 2 args={
/utils/if={instr("out","#1")}{check@out@sta},
/utils/if={instr("in","#1")}{check@in@sta},
/utils/if={instr("out","#2")}{check@out@tar},
/utils/if={instr("in","#2")}{check@in@tar}
}
并被用作[check outin={<start node>}{<target node>}]
。
两种解决方案都会检查给定的坐标是否包含out
和如果它们包含in
并应用check@[in|out]@[sta|tar]
样式。
如果名称包含 ,in
则连接将向西 ( ) 建立180
,如果out
包含 ,则连接将向东 ( 0
)。如果您将节点命名为inandout
,则in
将获胜,因为 的检查in
始终是最后一个。这不会检查您是否实际使用了节点名称。
注意,仅设置out
或之一,TikZ 将使用或in
的默认值绘制曲线。in = 135
out = 45
代码
\documentclass[tikz]{standalone}
\usepackage{xstring}
\makeatletter
\let\IFX\pgfutil@ifx
\pgfmathdeclarefunction{instr}{2}{%
\pgfutil@in@{#1}{#2}%
\ifpgfutil@in@\def\pgfmathresult{1}\else\def\pgfmathresult{0}\fi}
\pgfkeys{/utils/if/.code n args={3}{%
\pgfmathparse{#1}\ifdim\pgfmathresult pt=0pt\relax
\expandafter\pgfutil@firstoftwo\else\expandafter\pgfutil@secondoftwo\fi
{\pgfkeysalso{#3}}{\pgfkeysalso{#2}}}}
\makeatother
\tikzset{
check@out@sta/.style={out= 0},
check@in@sta/.style ={out=180},
check@out@tar/.style={in = 0},
check@in@tar/.style ={in =180},
check outin/.style={
/utils/if={instr("out","\tikztostart")}{check@out@sta},
/utils/if={instr("in","\tikztostart")}{check@in@sta},
/utils/if={instr("out","\tikztotarget")}{check@out@tar},
/utils/if={instr("in","\tikztotarget")}{check@in@tar}},
check outin xstring/.code 2 args={% #1 = start, #2 = target
\IfSubStr{#1}{out}{\pgfkeysalso{solid,check@out@sta}}{}%
\IfSubStr{#1}{in} {\pgfkeysalso{solid,check@in@sta}} {}%
\IfSubStr{#2}{out}{\pgfkeysalso{solid,check@out@tar}}{}%
\IfSubStr{#2}{in} {\pgfkeysalso{solid,check@in@tar}} {}}}
\newcommand*\doOutIn[3][]{
\IfStrEq{#2}{#3}{}{
\path[loosely dotted,#1] (#2) edge[check outin xstring={#2}{#3}] (#3);}}
\tikzset{every picture/.append style={nodes=draw,overlay,execute at end picture={
\useasboundingbox[overlay=false] (nope3.west) -- (nope2.south) --
([yshift=5mm]nope1.north) -- ([xshift=5mm]nope4.east);}}}
\begin{document}
\begin{tikzpicture}[
n/.style={sloped,above,allow upside down,font=\tiny,draw=none,scale=.5}]
\node (letmein) {in}; \node (checkmeout) at (2,1) {out};
\node (nope1) at (-2, 2) {nope1}; \node (nope2) at (-1,-2) {nope2};
\node (nope3) at (-3, 0) {nope3}; \node (nope4) at (2, -2) {nope4};
\foreach \sta[count=\i] in {letmein, checkmeout, nope1, nope2, nope3, nope4}
\foreach \tar[count=\j, evaluate={\col=(\i+10*\j)/66*100;}]
in {letmein, checkmeout, nope1, nope2, nope3, nope4} {\IFX\sta\tar{}{
\draw[red!\col!blue] (\sta) to[check outin] node[n]{\sta-\tar} (\tar);}}
\end{tikzpicture}
\begin{tikzpicture}
\foreach \sta[count=\i] in {letmein, checkmeout, nope1, nope2, nope3, nope4}
\foreach \tar[count=\j, evaluate={\col=(\i+10*\j)/66*100;}]
in {letmein, checkmeout, nope1, nope2, nope3, nope4} {
\doOutIn[red!\col!blue]{\sta}{\tar}}
\end{tikzpicture}
\end{document}
输出
答案3
根据 Qrrbrbirlbel 的评论,以下内容可按预期工作。
\documentclass{article}
\usepackage{tikz}
\newcommand{\pathoptions}{
out=0
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) to[style/.expand once=\pathoptions] (1,1);
\end{tikzpicture}
\end{document}
xstring
不幸的是,它似乎不能与我希望使用的包很好地配合- 以下代码失败,出现错误“\pgfkeyscurrentkey 定义中的参数编号非法”。
\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}
\newcommand{\pathoptions}{
\IfSubStr{test}{est}{
out=0
} {
in=180
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) to[style/.expand once=\pathoptions] (1,1);
\end{tikzpicture}
\end{document}