有没有办法在路径的“内部”或“外部”绘制 TikZ 线?

有没有办法在路径的“内部”或“外部”绘制 TikZ 线?

这个答案,杰克指出

miter选项更“正确”,因为它不会在形状上添加新角或引入圆角。但在某些情况下,如果角度非常尖锐,结果可能不理想,就像您链接到的问题一样……

在参照这个问题。对于非常锐角的情况,斜接接头会延伸到两条线相交的坐标之外,这当然是真的。从某种意义上说,这是因为 TikZ 以指定的坐标为中心绘制线条,这几乎总是理想的结果。但在这种情况下,最好将斜接的最外点指定为线条的“端点”,并让笔触完全不居中以及坐标的一侧或另一侧。Illustrator(例如,因为我手边有它)支持这一点,但只适用于封闭路径,其中路径有明确定义的“内部”和“外部”。对于锐角,您可以以半有意义的方式重复使用“内部”或“外部”,但该术语可能不适用于单条线...由于缺乏更好的术语,我将重复使用“上方”或“下方”或“左侧”或“右侧”,因为它们用于描述标签定位。

在 TikZ 中是否有一种方便的方法来指定线条是在其坐标的“上方”还是“下方”绘制的 --- 实际上是在垂直于线条的方向上偏移线宽的一半?是否有类似的解决方案可以在其坐标的“上方”或“下方”绘制曲线(虽然说“垂直于线条”不那么容易,但从数学上讲仍然是可能的)?如果没有针对任意开放路径的好的解决方案,那么是否有针对封闭路径的好的解决方案,就像在 Illustrator 中一样?

编辑:回答 Andrew 的问题,Illustrator 默认在“内部”和“外部”绘制以下路径:

Illustrator 的路径描边选项

顶部路径被选中,并以蓝色突出显示。该笔触为“默认”,即居中。中间是“内部”,分别绘制两个子区域。底部是“外部”。这是一个更曲折、更自相交的示例,它表明 Illustrator 具有斜接限制,以及一种似乎基于奇偶校验的算法:

曲折的道路

请注意,Illustrator 将“内部”和“外部”限制为仅在封闭路径上的实线描边:如果您尝试使用虚线描边,或者使用非封闭路径,或者尝试像 Andrew 的示例那样使用虎纹,它会禁用内部和外部选项,这让我怀疑是否存在方便的 PDF 或 PS 命令用于偏移简单路径上的简单描边,而不是更强大的解决方案......

我完全同意选择哪一边不是局部的,但另一方面,如果你为路径的第一段选择一个选项(例如,“从路径上的第一个点前往第二个点时,向右侧”),它将在路径的其余部分保持一致。

促使我提出这个问题的最初原因是尝试绘制一个边缘加厚的 3D 立方体。我很好奇你是否可以通过以下方式绘制该立方体:“绘制正面,向内描边。绘制(缩短的)顶面,向内描边。绘制(缩短的)侧面,向内描边。”在这种情况下,安德鲁的曲折路径不会出现,并且仍然有明确的内部和外部,目标是拥有适合立方体的尖角,因此斜接需要由最外点指定……

编辑:为了跟进我对 Andrew 的回答的评论问题,以下是 TikZ 对他的解决方案应用于他给出的 8 字形示例的结果。这里的路径以 8 字形绘制,从箭头方向开始。它们使用reverseclip来自的样式这个答案,并且使用的精确路径在剪辑版本上以彩色绘制:

Tikz 裁剪 8 字形路径

红色示例使用裁剪,并使“内部”与 Illustrator 的行为相匹配……但蓝色示例使用反向裁剪,并且在图像的右半部分会混淆。如果我以另一个方向绘制 8 字形,则红色示例保持不变,但蓝色示例在图像的左半部分会混淆。最后,完全相同的样式,但使用我上面的“曲折”路径:

Tikz 剪切曲折路径

红色和蓝色的路径都有点混乱,虽然它们不遵循 Illustrator 的奇偶算法,但我不知道下列的...

(最后,对于任何想要重现我所看到的行为的人来说,我使用的曲折路径的 TikZ 代码:

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

\begin{document}
\begin{tikzpicture}[remember picture,overlay,scale=2,line width=2mm]
\tikzstyle{reverseclip}=[insert path={(current page.north east) --
  (current page.south east) --
  (current page.south west) --
  (current page.north west) --
  (current page.north east)}
]
\draw (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\draw[green,line width=1pt] (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\begin{scope}[yshift=-2.5cm,line width=4mm]
\begin{scope}
\clip (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\draw (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\end{scope}
\draw[red,line width=1pt] (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\end{scope}
\begin{scope}[yshift=-5cm,line width=4mm]
\begin{pgfinterruptboundingbox}
\path[clip] (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle [reverseclip];
\draw (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\end{pgfinterruptboundingbox}
\draw[blue,line width=1pt] (0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle;
\end{scope}
\end{tikzpicture}
\end{document}

答案1

我当时正在思考该如何解决这个问题,突然想到了一个非常简单的解决方案。如果我知道这就是 Illustrator 的功能,我一点也不惊讶。看看这些图表,似乎就是这样。

我最初的计划是想出某种装饰,将路径“移”到左边或右边,但这似乎很困难。但我想不出让 TikZ 以不同的方式处理路径的两半的方法。后来我意识到有这样一种方法:剪辑。

当 TikZ 沿路径剪切时,该路径的两侧将以不同的方式处理。因此,这可用于使其仅绘制一侧。有点。您绘制一条路径,但将其沿自身剪切。由于剪切路径没有宽度,这意味着绘制了一半路径。“有点”是因为决定哪一半取决于被包围的区域,而不是路径的实际一侧。我认为这导致了问题中 Illustrator 图像的奇怪外观。

对此的一般解决方案是使用一个命令来同时绘制和剪辑。这可以用我的spath库来完成(仍在开发中,但可从启动板上的 TeX-SX 站点获取),并且必须使用此处某处的“反向”剪辑方法来处理另一侧。但为了演示这个概念,我们可以手动完成。这是立方体:

带剪辑的立方体

代码如下:

\documentclass{article}
%\url{http://tex.stackexchange.com/q/29991/86}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[scale=5,line width=2mm]
\draw (0,0,0) -- (1,0,0) -- (1,1,0) -- (0,1,0) -- cycle;
\draw (1,0,0) -- (1,0,-1) -- (1,1,-1) -- (1,1,0) -- cycle;
\draw (0,1,0) -- (0,1,-1) -- (1,1,-1) -- (1,1,0) -- cycle;
\begin{scope}[yshift=-2cm,line width=4mm]
\begin{scope}
\clip (0,0,0) -- (1,0,0) -- (1,1,0) -- (0,1,0) -- cycle;
\draw (0,0,0) -- (1,0,0) -- (1,1,0) -- (0,1,0) -- cycle;
\end{scope}
\begin{scope}
\clip (1,0,0) -- (1,0,-1) -- (1,1,-1) -- (1,1,0) -- cycle;
\draw (1,0,0) -- (1,0,-1) -- (1,1,-1) -- (1,1,0) -- cycle;
\end{scope}
\begin{scope}
\clip (0,1,0) -- (0,1,-1) -- (1,1,-1) -- (1,1,0) -- cycle;
\draw (0,1,0) -- (0,1,-1) -- (1,1,-1) -- (1,1,0) -- cycle;
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}

请注意限制剪辑的范围和加倍的线宽,因为我们在剪辑中丢失了一半。

答案2

这实际上是一条评论,但我想发布一张图片。本着“一张图片胜过千言万语...”的精神,您能告诉我 Illustrator 认为这条路径的内部和外部是什么吗:

莫比乌斯带

我意识到您说的是“路径的‘内部’和‘外部’定义明确”,因此 Illustrator 可能无法处理该示例。我想指出的是,该请求不是本地请求:您无法一致地定义任意路径的“内部”和“外部”。当您检查特定连接时,您必须考虑路径的所有其他部分,以确定应该发生什么。

另一种方法是让 TikZ 始终调整连接以将其移至内角。这会起作用,因为它是一个局部属性,并且函数在 \pi/2 处不连续这一事实并不重要,因为您永远不会注意到不连续性(这是一张罕见的图片,其中一系列线从整个角度范围汇聚到一点,为此您可以关闭该功能)。但是,我认为这并不能解决基本问题。连接仍然看起来很糟糕,只是会移动。以下是您将得到的简单示例:

在此处输入图片描述

(便宜,因为它也有外部路径,这是使用double选项完成的。)内线看起来和外线一样糟糕。

在任何图表或文档中,都会出现这样的情况:计算机必须说:“这是我最好的结果。”而人必须看看结果并说:“这不是我想要的,让我稍微调整一下。”。我认为你刚刚到达了这一点。TeX(以及 TikZ)的一大优点是,当你想关闭自动驾驶仪并恢复手动控制时,它会优雅而优雅地完成。

(正如我在开头所说的,这是一个评论,而不是答案。我相信有人可以实现一些可以自动完成这件事的东西,那将是一段很棒的代码。

答案3

混合解决方案,效果良好:

在此处输入图片描述

代码:

\documentclass[margin=4mm]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[line width=4mm,even odd rule]
  \tikzset{invclip/.style=
    {clip,insert path={(-16000pt,-16000pt) rectangle (16000pt,16000pt)}}%
  }
  % some paths to try...
  % \def\mypath{(0,1) -- (1,0) -- (4,2) -- (1,1) -- (4,1) -- (3,0) -- (1,2) -- (2.5,0) -- cycle}
  %\def\mypath{(0,0) -- (1,-1) -- (3,1) -- (4,0) -- (3,-1) -- (1,1) -- cycle}
  \def\mypath{(0,0) -- (1,1) -- (3,-1) -- (4,0) -- (3,1) -- (1,-1) -- cycle}
  % normal
  \draw \mypath;
  \draw[green,line width=1pt] \mypath;
  % inside
  \begin{scope}[yshift=-2.5cm,line width=4mm]
    \begin{scope}
      \clip \mypath;
      \draw \mypath;
    \end{scope}
    \draw[red,line width=1pt] \mypath;
  \end{scope}
  % outside
  \begin{scope}[yshift=-5cm,line width=4mm]
    \begin{pgfinterruptboundingbox}
      \path[invclip] \mypath;
      \draw \mypath;
    \end{pgfinterruptboundingbox}
    \draw[blue,line width=1pt] \mypath;
  \end{scope}
\end{tikzpicture}
\end{document}

“曲折”路径的结果:

在此处输入图片描述

答案4

一种方法是使用路径装饰器。它们不关注内部或外部,而是关注绘制路径的方向。

这并不是原始发帖人所问的,但这可能是解决方案的开始。请参阅下面的示例和代码。

使用路径装饰器可能实现的功能的一个示例。

http://www.texample.net/tikz/examples/lipid-vesicle/

相关内容