解决方案 A

解决方案 A

注意:以下问题与最终版本类似这个问题,但该问题的答案似乎都没有回答我的问题。

通常,我发现通过指定曲线经过具有特定切线的某些点来指定曲线是可取的。例如,我可能想要指定一条曲线从(0,0)10 度角开始,然后经过(1,1)70 度倾斜处、(2,2)0 度倾斜处和(3,0)-50 度倾斜处(按此顺序)。以下代码可实现此目的:

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
    \draw (0,0) to[out=10,in=70-180] (1,1)%
        to[out=70,in=0-180] (2,2)%
        to[out=0,in=-50-180] (3,0);
\end{tikzpicture}
\end{document}

图片

然而,我发现这很尴尬,原因有几个,其中最重要的一个是:如果我想摆弄某个点的切线,我必须改变两个数字,而不仅仅是一个。

我希望能够写出类似以下内容的内容:

\begin{tikzpicture}
    \draw (0,0) to[start angle=10,next angle=70] (1,1)%
        to[next angle=0] (2,2)%
        to[next angle=-50] (3,0);
\end{tikzpicture}

这种语法避免了冗余,而且更直观,至少对我来说是这样。不幸的是,我使用 type 命令实现它的尝试\pgfkeys迄今为止没有成功。

如何实现上述类似的事情?(形象地说,避免使用低级 TeX 命令可以获得加分。)

答案1

解决方案 A

该解决方案提供了两种 TikZ 样式:

  • next angle这样做就是你想要的:
    • 使用提供的角度前进 180 度作为in角度(在下一个坐标处)
    • 使用上次保存的角度next angle作为out角度
    • next angle在宏中保存提供的角度\nextAngle这样它在to path计算当前值之后就会被设置,并且宏可用于下一个to path
  • start angle只是 的一个克隆out。此外,它还进行了设置\nextAngle,以便可以在 之前使用next angle
    顺序next anglestart angle/out也可以工作,但out→不行next angle

代码

\documentclass[tikz]{standalone}
\def\nextAngle{0}
\tikzset{
    next angle/.style={
        in=#1+180,
        out=\nextAngle,
        prefix after command= {\pgfextra{\def\nextAngle{#1}}}
    },
    start angle/.style={
        out=#1,
        nangle=#1,
    },
    nangle/.code={% used only internally
        \def\nextAngle{#1}
    }
}
\begin{document}
\begin{tikzpicture}
    \draw (0,0) to[out=10, in=70-180] (1,1)
                to[out=70, in=0-180]  (2,2)
                to[out=0, in=-50-180] (3,0);
\end{tikzpicture}
\begin{tikzpicture}
    \draw (0,0) to[start angle=10,next angle=70] (1,1)
                to[next angle=0]                 (2,2)
                to[next angle=-50]               (3,0);
\end{tikzpicture}
\end{document}

输出

直线进近

解决方案 B(“51 区”)

该解决方案提供了一些 TikZ 样式:

  • start angle仅仅是 的一个克隆out
  • next angle做你想做的事:
    • 使用提供的角度前进 180 度作为in角度(在下一个坐标处)
    • 保存所提供的角度以便next angle在下一个角度中使用(这会产生很大的影响,因为它还设置了样式- 这是和的基础- 即使在未以任何方式指定的 s 中也可以使用它)。to pathoutcurve toto pathoutinto
  • last angle是 的克隆in,但添加了自定义度数。此外,将设置180样式,以便下一个将恢复其正常行为(参见上面的注释)。line toto
  • last angle simple就像last angle除了line to不会被设置之外。

笔记:默认值与(意思是:无论我的代码做什么,都会一直有效)to相同。----

下面给出的例子中可以更好地看到最后三种风格之间的差异。

我担心这种方法会对to path和造成太大的影响curve to。因此,我认为解决方案 A 更好。

代码

\documentclass[tikz]{standalone}
\def\nextAngle{0} % old solution
\tikzset{
    next angle/.style={
        in=#1+180,
        prefix after command={\pgfextra{\tikzset{out=#1}}}
    },
    start angle/.style={out=#1},
    last angle/.style={
        in=#1+180,
        prefix after command={\pgfextra{\tikzset{line to}}} % revert to default to path
    },
    last angle simple/.style={in=#1+180}
}
\begin{document}
\begin{tikzpicture}
\fill[black!15] (-.5,-1) rectangle (4.5,4);
\coordinate (a) at (0,0); \coordinate (b) at (1,1);
\coordinate (c) at (2,2); \coordinate (d) at (3,0);
\coordinate (e) at (3,3);

\draw[very thick,black] (a) to[start angle=10,next angle=70] (b)
            to[next angle=0]                 (c)
            to[next angle=-50]               (d)
            to                               (e); % uses out=-50
\draw[green!70!black] (a) to[start angle=10,next angle=70] (b)
            to[next angle=0]                 (c)
            to[last angle=-50]               (d)
            to                               (e);
\draw[blue] (a) to[start angle=10,next angle=70] (b)
                to[next angle=0]                 (c)
                to[last angle simple=-50]        (d) to (e);
\foreach \c in {a,...,e}{
  \fill[fill=red,opacity=.8] (\c) circle[radius=2pt] node[below] {\c};
}
\end{tikzpicture}
\end{document}

输出

传奇:

  • 厚,黑色:next angle=-50倒数第二个to
  • 蓝色:last angle=-50倒数第二个to
  • 绿色:last angle simple=-50倒数第二个to

不太直接的方法

答案2

以下是使用不同方法生成平滑曲线的解决方案:Hobby 算法使用 Metapost 和 TikZ 通过一系列点绘制曲线(在这个特殊情况下,因为切线是在每个点上指定的,所以不使用完整的算法,而只使用从控制点和角度定义的路径)。但是,它需要最新版本的代码,目前位于TeX-SX 启动板(下载hobby.dtx并运行tex hobby.dtx以生成文件)。

我喜欢此解决方案语法的一点是,切线是在它们所属的点处指定的。指定角度依赖于这样一个事实:由于算法的实现,坐标选项最终会被读取两次:一次在前一个段的末尾,一次在当前段的开头。因此,out如果尚未设置角度(意味着我们在起点),我们将设置角度,并将角度设置in180+<angle>(始终设置这个角度非常安全)。该行hobby action={\def\outangle{}}重置了标志,因此我们知道out下次要设置操作。

\documentclass{article}
%\url{https://tex.stackexchange.com/q/81604/86}
\usepackage{tikz}
\usetikzlibrary{hobby}

\def\outangle{}
\tikzset{
  tangent/.style={%
    in angle={(180 + #1)},
    maybe out angle=#1,
    hobby finish,
    hobby action={\def\outangle{}},
  },
  maybe out angle/.code={%
    \ifx\outangle\empty
    \pgfkeysalso{out angle=#1}%
    \def\outangle{t}%
    \fi
  }
}

\begin{document}
\begin{tikzpicture}[use Hobby shortcut]
    \draw ([tangent=10]0,0) .. ([tangent=70]1,1) .. ([tangent=0]2,2) .. ([tangent=-50]3,0);
\end{tikzpicture}

\end{document}

为了进行比较,这里是各种曲线。

爱好切线

以下是针对并非所有切线都已设置的问题的修复方法:

\newif\ifhobbyatend
\hobbyatendtrue
\tikzset{
  tangent/.style={%
    maybe in angle={(180 + #1)},
    maybe out angle=#1,
    hobby finish,
    hobby action={\global\hobbyatendfalse}
  },
  maybe out angle/.code={%
    \ifhobbyatend
    \else
    \pgfkeysalso{out angle=#1}%
    \global\hobbyatendtrue
    \fi
  },
  maybe in angle/.code={%
    \ifhobbyatend
    \pgfkeysalso{in angle=#1}%
    \fi
  }
}

(注意:在下一次上传到 Launchpad 时 - 在撰写本文时尚未发生但很快就会发生 - 我将键更改为hobby使其Hobby更清楚地表明这是某人的名字。因此,如果 LaTeX 抱怨hobby其中有未知的键,请尝试使用Hobby。)

相关内容