有没有一种好的方法可以在 TikZ 中创建一条只有部分部分被描边的路径?我想用一个命令创建整个路径,以便可以填充它,但我还想描边填充区域边界的某些部分,但不是全部。到目前为止,我想到最好的解决方案是edge
在路径中间使用操作来进行描边;例如,这是一个绿色填充的正方形,其中一条边被描边:
\path[fill=green] (0,0) -- (1,0) edge (1,1) -- (1,1) -- (0,1) -- cycle;
这比
\path[fill=green] (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
\draw (1,0) -- (1,1);
但是它仍然需要给出两次绘制从 (1,0) 到 (1,1) 的线段的命令,如果是贝塞尔曲线等更复杂的命令,这会很烦人且容易出错,如果是圆弧等无法通过命令绘制的东西edge
(至少,如果不编写自定义“to path”),则不可能。有什么建议吗?
答案1
这是对 Jan 代码的重新编写,使其更像 TikZ。它仍然做同样的事情:重复路径,一次作为填充,一次作为绘制,但在绘制阶段删除了路径的某些部分。主要的修改是(希望)它现在看起来与标准 TikZ 命令完全一样。
\documentclass{article}
\usepackage{tikz}
\makeatletter
\long\def\my@drawfill#1#2;{%
\@skipfalse
\fill[#1,draw=none] #2;
\@skiptrue
\draw[#1,fill=none] #2;
}
\newif\if@skip
\newcommand{\skipit}[1]{%
\if@skip
\else
#1
\fi
}
\newcommand{\drawfill}[1][]{%
\my@drawfill{#1}}
\makeatother
\begin{document}
\begin{tikzpicture}
\drawfill[fill=green,draw=blue,ultra thick] (0,0) -- (0,1) \skipit{--} (1,1) -- (1,0) \skipit{.. controls +(0,-1) and +(0,-1) ..} (0,0);
\end{tikzpicture}
\end{document}
得出的结果为:
我确信还有更多改进空间,这也是我创建这个社区 wiki 的原因之一(另一个原因是它实际上是 Jan 的答案)。特别是:
我无法让
\skipit
命令接受可选参数并仍然工作。我认为在真正的 TikZ 命令看到它之前它没有正确扩展,并且它们不喜欢将宏作为路径规范的一部分。键值对的分配有点儿像 hack:基本上,我们在填充命令上关闭绘图,并在绘制命令上关闭填充。能够指定一组只放在绘制命令上的键和一组只放在填充命令上的键可能会很有用,所以类似于
\drawfill[options for both, fillopt={options for fill}, drawopt={options for draw}]
但我对此了解不多(任何东西),pgfkeys
所以不知道该怎么做。
答案2
如果我理解正确的话,您想要做的就是只需输入一次路径。 类似这样的方法可行吗(它不遵循通常的 tikz 语法,但修复起来应该不难)?
\documentclass[]{article}
\usepackage{tikz}
\def\drawfill#1#2#3{{\def\skip{--}\fill[#1]#3;}{\def\skip{}\draw[#2]#3;}}
\begin{document}
\begin{tikzpicture}
\drawfill{fill=green}{very thick}{(0,0) -- (0,1) \skip (1,1) -- (1,0)\skip (0,0)}
\end{tikzpicture}
\end{document}
答案3
我使用库找到了新的解决方案decorations
。我们使用show path construction
装饰将路径分成几部分。只有在设置了某个标志时,我们才会渲染这些部分。诀窍是想出一种方法来输入路径,这样我们就可以指定标志切换而不会显著干扰路径。我确定的方法是使用长度为零的线作为切换。
\documentclass{standalone}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}
\newbool{partpath}
\pgfkeys{/tikz/partial rendering/.style={
postaction={
decorate,
decoration={
show path construction,
moveto code={
\global\booltrue{partpath}
},
lineto code={
\ifx\tikzinputsegmentfirst\tikzinputsegmentlast
\ifbool{partpath}{\global\boolfalse{partpath}}{\global\booltrue{partpath}}
\fi
\ifbool{partpath}{
\draw (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
}{}
},
curveto code={
\ifbool{partpath}{
\draw (\tikzinputsegmentfirst) .. controls (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb) .. (\tikzinputsegmentlast);
}{}
},
closepath code={
\ifbool{partpath}{
\draw (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
}{}
}
}
}
}
}
\begin{document}
\begin{tikzpicture}
\path[fill=green,partial rendering]
(0,0) -- (0,1) -- +(0,0) -- (1,1) -- +(0,0) -- (1,0) -- +(0,0) .. controls +(0,-1) and +(0,-1) .. (0,0);
\end{tikzpicture}
\end{document}
所有这些-- +(0,0)
s 都用于在第二次绘制路径时切换渲染。(我尝试使用空moveto
s:只是+(0,0)
,但是那里有这些会弄乱填充程序。)结果:
答案4
我希望证明我是错的,但我认为如果不绘制两次路径,这是不可能的。TikZ 手册 (v2.10) 第 12.3.3 节指出:
请注意,许多选项仅适用于整个路径,无法以这种方式限定范围。例如,无法限定路径的颜色范围。有关更多详细信息,请参阅路径部分中的说明。
以及第 14.16 节:
当 TikZ在路径操作应该出现的某个位置遇到左括号或右括号(
{
或)时,它将打开或关闭范围。所有可以“本地”应用的选项都将在范围内。例如,如果您在范围区域内应用转换,则移位仅适用于范围。另一方面,选项在范围内没有任何效果,因为它只能应用于整个路径。}
[xshift=1cm]
color=red
问题似乎是虚线图案应用于整个路径。大多数情况下,这是一件好事,因为这意味着虚线可以很好地跨越拐角。
因此我将其分解为几个命令:
\begin{tikzpicture}
\path[fill=green] (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
\draw (1,1) -- (0,1) -- (0,0) -- (1,0);
\draw[dashed] (1,0) -- (1,1);
\end{tikzpicture}
对于更复杂的路径,您可能需要将路径的某些部分存储到 TeX 宏中。