21

When I place a decoration at the end of a to path with "bend left=..." or "bend right=...", the decorations disappear at high bend angles:

\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}

enter image description here

Is this a bug in Tikz?

  • 6
    As a workaround you can use mark=at position 0.99 instead of mark=at position 1. Seems like some round off error. – Peter Grill May 15 '18 at 20:01
  • 2
    An example shown in the manual (v3.0.1a, page 587) implies that mark=at position -0.1pt works. If we replace -0.1pt with factor 1, the example will also fail. So this might be an issue known by the author. Maybe you should just avoid using 1 in a complex curve. – wklchris May 16 '18 at 20:58
  • 1
    Cool, didn't know that one can also give absolute positions on a path. And do I understand correctly that the positions are interpreted modulo the length of the path such that -0.1pt will be just right before the path end, independent of its length? – Andi Bauer May 17 '18 at 15:37
  • 1
    @AndiBauer Yeah. You can check that section of the manual for details. The syntax allows either a factor or an abosolute distance. – wklchris May 17 '18 at 17:32
  • 1
    @PeterGrill Can you add an answer ? That is actually the credible source of the problem – percusse May 21 '18 at 16:09
17
+100

That's a very interesting observation, but you could achieve the desired output very easily with the arrows.meta library.

\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}

enter image description here

IMHO this suggests that it is not a bug, rather the start and end points are to be dealt with arrows methods. It is not too surprising that these special points can cause some issues when used in decorations. Notice that in these decorations you are always in the tangent coordinate system at a given point of the path. (Of course, when your decoration is a circle, you cannot appreciate it, but if you were to place \draw (0,-2pt) -- (0,2pt); you'd see that this is orthogonal to the path at the given point). And clearly this tangent coordinate system is ill-defined at the ends of the curve. However, arrows are "trained" to deal with this, and thus there is no issue.

ADDENDUM: I do not think it is (only) a round-off error. Consider the 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}

It produces like in the OP's case

enter image description here

NOTE: None of the circles in the middle has been drawn.

However, once I remove

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

I get

enter image description here

IMHO this is not explainable as rounding error. Or am I doing something stupid?

ANOTHER ADDENDUM: In order to see why that happens at a more technical level, I added a typeout to \pgf@decorate@@movealongpath in pgfmoduledecorations.tex such that it becomes

\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%
}

which leads to the typeouts

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

where the numbers are the respective angles. This means that at the too high angle the remaining distance becomes negative (or nonpositive to be more precise), which it probably should not, and hence the decoration gets suppressed. So I guess it is fair to say that

  • Yes, a rounding error plays a role in the explanation, but it is probably fair to say that they are not the sole explanation. Naively, I would expect a rounding error to just move a decoration, not to swallow it. However, digging into the code I believe to have identified the piece of code that is responsible for the disappearance of the decorations.

  • J Leon V.'s observation are consistent with that. Yet I am not sure that they explain why this happens. But I am also not claiming this answer truly explains why the above if statement has been implemented.

  • On the other hand, I think this answer provides a reliable way of placing the decorations where they should be. (I also see that my statement on the derivative above is not to the point. I keep it for historical reasons. I also think I could defend it by reminding the reader that the arc length is integrated as an integral over the length of the tangent, but this is not what I had in mind when I wrote the statement.)

  • I don't see why the tangent vector should be ill-defined at the ends of a curve. For the point 0 it works fine. Maybe it takes the derivative numerically into the direction of the line which fails at 1. But that still doesn't explain why it does work for some angles. – Andi Bauer May 16 '18 at 7:59
  • I exactly want to use this rotated coordinate system feature to place a node after the line end, see: tex.stackexchange.com/q/431650/163063. Can one use the arrows method for this also? – Andi Bauer May 16 '18 at 8:00
  • .. And as for your first comment: I assume that you know how mathematicians define differentiability and that you need a (small) neighborhood around the point. – user121799 May 16 '18 at 14:28
  • @marmot you're right, at the end of the path the differentiation should be the one-side type (en.wikipedia.org/wiki/Semi-differentiability ), left- or right- given the case. – Rmano May 21 '18 at 18:40
  • 1
    Not really THE answer, but very useful if someone wants to nail the bug... And the bounty was expiring.... – Rmano May 27 '18 at 20:37
16

It's interesting, so the error is in the algorithm that disappears the decorations when the line is finished, for example, if I use a defined length to position them, if they exceed the length of the line, the points disappear as the next result.

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

enter image description here

In my first iteration probe with varying the position by percent of line:

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

enter image description here

The first observation is that the foreach algorithm when calculating the step, adds decimals, is not limited to the decimals of the step. If I make the steps in thousandths, I get this.

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

enter image description here

Here you can see that the error occurs, even with values close to 1, then, probe with values close to 1 increasing the accuracy with more decimals, and I got this.

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

enter image description here

As you can see the error is caused when approaching in 4 cecimals.The algorithm that locates the origin of the decoration in the line has a limited exatitude, probably due to the calculation length of the variables, while the bend angle, makes the ongitude of this line have a value with more or less decimals, that make the other algorithm that decides where the mark disappears can not decide the limit correctly. Will there be some configuration to increase the calculation bits in the algorithms?

MWE:

% 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}

For Animation I use ImageMagic portable version, embedded in arara in animate yaml file.

12

Seems like a round off error to me. As a workaround you can use mark=at position 0.99 instead of mark=at position 1. Seems like some round off error.

enter image description here

Code:

\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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.