Tikz:路径末端的装饰在高弯曲角度下消失

Tikz:路径末端的装饰在高弯曲角度下消失

当我使用“向左弯曲=...”或“向右弯曲=...”在路径末尾放置装饰时,装饰会在弯曲角度较大时消失:

\documentclass[border = 2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\tikzset{enddot/.style={
    decoration={markings, mark=at position 1 with {
    \fill (0,0)circle(2pt);
    }}, postaction={decorate}}}
\begin{document}
\begin{tikzpicture}
\foreach \angle in {0,10,...,80}{
\draw[enddot] (0,0)to[bend right=\angle](\angle:2);
}
\end{tikzpicture}
\end{document}

在此处输入图片描述

这是 Tikz 的一个错误吗?

答案1

这是一个非常有趣的观察,但您可以使用 arrows.meta 库非常轻松地实现所需的输出。

\documentclass[border = 2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}
\foreach \angle in {0,10,...,80}{
\draw[-Circle] (0,0)to[bend right=\angle](\angle:2);
}
\end{tikzpicture}
\end{document}

在此处输入图片描述

在我看来,这不是一个错误,而是起点和终点要用箭头方法处理。这些特殊点在装饰中使用时会引起一些问题,这并不奇怪。请注意,在这些装饰中,您始终处于路径给定点的切线坐标系中。(当然,当您的装饰是一个圆圈时,您无法欣赏它,但如果您放置它,\draw (0,-2pt) -- (0,2pt);您会看到它在给定点处与路径正交)。显然,这个切线坐标系在曲线的末端定义不明确。但是,箭头经过“训练”可以处理这个问题,因此不存在问题。

附录: 我愿意不是认为这只是一个舍入误差。考虑 MWE

\documentclass[border = 2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\tikzset{enddot/.style={
    decoration={markings, 
    mark=at position 1 with {
    \fill (0,0)circle(2pt);
    },
    mark=at position 0.5 with {
    \fill (0,0)circle(2pt);
    }}, postaction={decorate}}}
\begin{document}
\begin{tikzpicture}
\foreach \angle in {0,10,...,80}{
\draw[enddot] (0,0)to[bend right=\angle](\angle:2);
}
\end{tikzpicture}
\end{document}

它产生的结果与 OP 的情况类似

在此处输入图片描述

笔记:中间的圆圈一个都没画出来。

然而,一旦我删除

    mark=at position 1 with {
    \fill (0,0)circle(2pt);
    },

我明白了

在此处输入图片描述

恕我直言,这不能用舍入误差来解释。还是我做了什么蠢事?

另一附录:为了从技术层面了解为什么会发生这种情况,我在\pgf@decorate@@movealongpathin 中添加了一个 typeout pgfmoduledecorations.tex,使其变为

\def\pgf@decorate@@movealongpath{%
  \advance\pgfdecoratedinputsegmentcompleteddistance\pgf@decorate@distancetomove%
  \advance\pgfdecoratedinputsegmentremainingdistance-\pgf@decorate@distancetomove%
  \ifdim\pgfdecoratedinputsegmentremainingdistance>0pt\relax%
    \let\pgf@next\pgf@decorate@@@movealongpath%
  \else%
          \typeout{gotcha}
    \pgf@decorate@distancetomove-\pgfdecoratedinputsegmentremainingdistance%
    \pgf@decorate@processnextinputsegmentobject%
    \ifx\pgf@decorate@currentinputsegmentobjects\pgfutil@empty%
      \pgfdecoratedremainingdistance0pt\relax%
      \let\pgf@next\relax%
    \else%
      \let\pgf@next\pgf@decorate@@movealongpath%
    \fi%
  \fi%
  \pgf@next%
}

这导致了打字

0
gotcha
10
gotcha
20
gotcha
30
gotcha
40
50
60
70
80

其中数字是相应的角度。这意味着在角度过大时,剩余距离变为负数(或更准确地说是非正数),这可能不应该,因此装饰被抑制。所以我认为可以公平地说

  • 是的,舍入误差在解释中起到了一定作用,但公平地说,它们并不是唯一的解释。天真地,我以为舍入误差只是移动装饰,而不是吞掉它。然而,深入研究代码后,我相信已经确定了导致装饰消失的代码片段。

  • J Leon V. 的观察与此一致。但我不确定他们解释为什么会发生这种情况。但我也不认为这个答案真正解释了为什么上述if语句已经实现。

  • 另一方面,我认为这个答案提供了一种将装饰物放置在应有位置的可靠方法。(我还看到我对上述导数的陈述并不切题。我出于历史原因保留它。我也认为我可以通过提醒读者弧长是切线长度的积分来为其辩护,但这不是我写这句话时所想的。)

答案2

这很有趣,所以错误是在算法中,当线完成时装饰就会消失,例如,如果我使用定义的长度来定位它们,如果它们超出了线的长度,那么点就会作为下一个结果消失。

\foreach \distance in {0.9,1.92,...,2.5} 
...
...mark=at position \distance cm with ... % position in cm.

在此处输入图片描述

在我第一次迭代探测中,根据线的百分比改变位置:

\foreach \distance in {0.90,0.91,...,1.05} 

在此处输入图片描述

第一个观察结果是,foreach 算法在计算步长时会添加小数,并不局限于步长的小数。如果我将步长设为千分之一,就会得到这个结果。

\foreach \distance in {0.99,0.991,...,1.01}

在此处输入图片描述

在这里您可以看到,即使值接近 1,也会出现错误,然后,用接近 1 的值进行探测,使用更多的小数来提高精度,我就得到了这个。

\foreach \distance in {0.9,0.99,0.999,0.9999,0.99999,0.999999,1,1.0009} 

在此处输入图片描述

如您所见,错误是由于接近 4 个零位造成的。定位装饰线起点的算法具有有限的极限,可能是由于变量的计算长度,而弯曲角度使该线的经度具有或多或少的小数值,这使得决定标记消失位置的其他算法无法正确确定极限。是否会有一些配置来增加算法中的计算位数?

梅威瑟:

% arara: pdflatex: {synctex: yes, action: nonstopmode}
% arara: animate: {density: 200, delay: 200, other: -background white -alpha remove}
% arara: showanimate
\documentclass[tikz,border = 2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
    \foreach \distance in {0.9,0.99,0.999,0.9999,0.99999,0.999999,1,1.000009}
    {
        \begin{tikzpicture}
        % fill circle and plot
        \foreach \angle in {0,10,...,80}{
            \draw[decoration={markings, mark=at position \distance with {
                    \fill[red] (-1pt,-1pt) rectangle (1pt,1pt);
            }}, postaction={decorate}] (0,0)to[bend right=\angle](\angle:2);
        }
        \draw (-0.5,-0.2) rectangle (2.5,2.5);
        \node (a) at (1,2.25) {\tiny Mark position=\distance } ;
        \end{tikzpicture}
    }
\end{document}

对于动画,我使用 ImageMagic 便携版本,嵌入在动画 yaml 文件中的 arara 中。

答案3

对我来说这似乎是舍入错误。作为一种解决方法,您可以使用mark=at position 0.99而不是mark=at position 1。这似乎是舍入错误。

在此处输入图片描述

代码:

\documentclass[border = 2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\tikzset{enddot/.style={
    decoration={markings, mark=at position 0.99 with {
    \fill[red] (0,0) circle (2pt);
    }}, postaction={decorate}}}
\begin{document}
\begin{tikzpicture}
\foreach \angle in {0,10,...,80}{
\draw[enddot] (0,0)to[bend right=\angle](\angle:2);
}
\end{tikzpicture}
\end{document}

相关内容