使用新命令设置 tikz 路径选项

使用新命令设置 tikz 路径选项

笔记:我刚刚意识到这个问题的答案可能对我没有帮助——我已经忘记了这个问题在 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

我将展示两种解决方案:

  1. 第一个只使用 TikZ/PGFkeys,借助

    • /utils/if={<cond>}{<true kv>}{<false kv>}测试<cond>并应用<true kv>的密钥<false kv>
    • 调用一个 PGFmath 函数,当处于时instr("<sub>","<text>")返回1(true) ,否则返回 (false)。<sub><text>0
  2. 第二种解决方案使用使用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 = 135out = 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}

相关内容