Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plot option smooth and decorations.markings #748

Closed
ghost opened this issue Sep 16, 2019 · 13 comments
Closed

Plot option smooth and decorations.markings #748

ghost opened this issue Sep 16, 2019 · 13 comments

Comments

@ghost
Copy link

ghost commented Sep 16, 2019

There is an interesting interplay between the plot option smooth and decorations.marking (but most likely not only for markings decorations). Consider the MWE

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{calc,decorations.markings}
\begin{document}
\begin{tikzpicture}[scale=2,pics/coordsys/.style = {
    code = {
        \draw [->,pic actions] (0,0) -- +(1,0)[red] node[pos=1.1]
		{$x$};
        \draw [->,pic actions] (0,0) -- +(0,1)[blue] node[pos=1.1,
		%rotate=00,
		%transform shape,
		%transform shape=false
		]
		{$y$};
    }},rotated coordsys at/.style={postaction={decorate,decoration={markings,
mark=at position #1 with {
\path (0,0) coordinate (O') (1,0) coordinate (X');
\path let \p1=($(X)-(O)$),\p2=($(X')-(O')$) in \pgfextra{%
\pgfmathsetmacro{\myangle}{atan2(\y1,\x1)-atan2(\y2,\x2)}
\xdef\myangle{\myangle}};
\pgftransformresetnontranslations
 \path (O') pic[solid,rotate=-\myangle]{coordsys};
}}}}]
 \path (0,0) coordinate (O) (1,0) coordinate (X);
 \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}] 
	plot[variable=\x,domain=-2:2] (\x,{sin(\x*45)});
 \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}] 
  plot[variable=\x,domain=-2:2,samples=25,smooth] (\x+5,{sin(\x*45)});
\end{tikzpicture}
\end{document}

image

As one can see, on the left side, where a nonsmooth plot is employed, the y is upright. On the other hand, on the right side where the plot has the smooth key, it is not. The difference in behavior is already surprising to me. However, what is worse, I am unable to cure it (other than explicitly computing the rotation angle that rotates it back to upright). I played with the usual suspects like tansform shape, rotate, \pgftransformresetnontranslations in all combinations I could think of but could not fix it.

P.S. It does not seem to be related to the usage of a pic.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{calc,decorations.markings}
\begin{document}
\begin{tikzpicture}[scale=2,rotated coordsys at/.style={postaction={decorate,decoration={markings,
mark=at position #1 with {
\path (0,0) coordinate (O') (1,0) coordinate (X');
\path let \p1=($(X)-(O)$),\p2=($(X')-(O')$) in \pgfextra{%
\pgfmathsetmacro{\myangle}{atan2(\y1,\x1)-atan2(\y2,\x2)}
\xdef\myangle{\myangle}};
%\pgftransformresetnontranslations
 \draw [->] (O') -- +(1,0)[red] node[pos=1.1]
		{$x$};
 \draw [->] (O') -- +(0,1)[blue] node[pos=1.1,
		%rotate=00,
		%transform shape,
		%transform shape=false
		]
		{$y$};
}}}}]
 \path (0,0) coordinate (O) (1,0) coordinate (X);
 \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}] 
	plot[variable=\x,domain=-2:2] (\x,{sin(\x*45)});
 \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}] 
  plot[variable=\x,domain=-2:2,samples=25,smooth] (\x+5,{sin(\x*45)});
 \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}]  (-2,-1) to[bend right] 
  (2,-1);
\end{tikzpicture}
\end{document}

has the same issue.

@hmenke
Copy link
Member

hmenke commented Sep 16, 2019

I don't remember touching any decorations or plot code, so if this is a regression it must be really old.

@ghost
Copy link
Author

ghost commented Sep 16, 2019

@hmenke OK, I remove the parentheses.

@hmenke
Copy link
Member

hmenke commented Sep 16, 2019

This is the plot handler that is used when the smooth option is active:

% This handler converts each plot stream command into a curveto
% command, except for the first, which is converted to the previously
% specified action.
%
% Example:
%
% \pgfpathmoveto{\pgfpointorigin}
% \pgfsetlinetofirstplotpoint
% \pgfplothandlercurveto
% \pgfplotxyfile{mytable}
\pgfdeclareplothandler{\pgfplothandlercurveto}{}{%
point macro=\pgf@plot@curveto@handler@initial,
jump macro=\pgf@plot@smooth@next@moveto,
end macro=\pgf@plot@curveto@handler@finish
}%
\def\pgf@plot@smooth@next@moveto{%
\pgf@plot@curveto@handler@finish%
\global\pgf@plot@startedfalse%
\global\let\pgf@plotstreampoint\pgf@plot@curveto@handler@initial%
}%
\def\pgf@plot@curveto@handler@initial#1{%
\pgf@process{#1}%
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@plot@first@action{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
\xdef\pgf@plot@curveto@first{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
\global\let\pgf@plot@curveto@first@support=\pgf@plot@curveto@first%
\global\let\pgf@plotstreampoint=\pgf@plot@curveto@handler@second%
}%
\def\pgf@plot@curveto@handler@second#1{%
\pgf@process{#1}%
\xdef\pgf@plot@curveto@second{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
\global\let\pgf@plotstreampoint=\pgf@plot@curveto@handler@third%
\global\pgf@plot@startedtrue%
}%
\def\pgf@plot@curveto@handler@third#1{%
\pgf@process{#1}%
\xdef\pgf@plot@curveto@current{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
% compute difference vector:
\pgf@xa=\pgf@x%
\pgf@ya=\pgf@y%
\pgf@process{\pgf@plot@curveto@first}
\advance\pgf@xa by-\pgf@x%
\advance\pgf@ya by-\pgf@y%
% compute support directions:
\pgf@xa=\pgf@plottension\pgf@xa%
\pgf@ya=\pgf@plottension\pgf@ya%
% first marshal:
\pgf@process{\pgf@plot@curveto@second}%
\pgf@xb=\pgf@x%
\pgf@yb=\pgf@y%
\pgf@xc=\pgf@x%
\pgf@yc=\pgf@y%
\advance\pgf@xb by-\pgf@xa%
\advance\pgf@yb by-\pgf@ya%
\advance\pgf@xc by\pgf@xa%
\advance\pgf@yc by\pgf@ya%
\edef\pgf@marshal{\noexpand\pgfpathcurveto{\noexpand\pgf@plot@curveto@first@support}%
{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}{\noexpand\pgf@plot@curveto@second}}%
{\pgf@marshal}%
% Prepare next:
\global\let\pgf@plot@curveto@first=\pgf@plot@curveto@second%
\global\let\pgf@plot@curveto@second=\pgf@plot@curveto@current%
\xdef\pgf@plot@curveto@first@support{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
}%
\def\pgf@plot@curveto@handler@finish{%
\ifpgf@plot@started%
\pgfpathcurveto{\pgf@plot@curveto@first@support}{\pgf@plot@curveto@second}{\pgf@plot@curveto@second}%
\fi%
}%

@ghost
Copy link
Author

ghost commented Sep 16, 2019

@hmenke I do not think it is the plot handler but Bezier vs. straight lines.

 \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}]  (-2,-1) to[bend right] 
  (2,-1);

has the same issue.

@hmenke
Copy link
Member

hmenke commented Sep 16, 2019

Which is kind of the same statement, because the plot handler looks pretty innocent, so it probably comes from \pgfpathcurveto. Do you have an old version at hand with which you could test whether this is a regression?

@ghost
Copy link
Author

ghost commented Sep 16, 2019

@hmenke I agree that it is the same thing. All I wanted to say is that it is not the plot handler but the way TikZ switches to the tangent system. And I do not have an old version at hand at the moment.

@hmenke
Copy link
Member

hmenke commented Sep 16, 2019

I quickly tested with TeX Live 2015 and 2016 and they both exhibit the same broken behaviour as the latest master.

@ghost
Copy link
Author

ghost commented Sep 16, 2019

@hmenke OK, thanks! (I did not see this issue in the various tangent solutions on the TeX-SE site.)

@hmenke hmenke added the pic label Sep 16, 2019
@hmenke
Copy link
Member

hmenke commented Sep 16, 2019

I just realized that you are using a pic. There are some known issues with pic, so that might be the source of the problem.

@ghost
Copy link
Author

ghost commented Sep 16, 2019

@hmenke Does not seem like it. If you replace the pic by its code , the same issue arises.

@Mo-Gul
Copy link
Contributor

Mo-Gul commented Sep 16, 2019

Regarding "old versions": You can find all -- or at least most of them -- on https://sourceforge.net/projects/pgf/files/pgf/.

@hmenke hmenke added this to the 3.1.6 milestone Dec 17, 2019
@hmenke
Copy link
Member

hmenke commented Jun 17, 2020

Here is your fix.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
\begin{tikzpicture}[
    rotated coordsys at/.style={
        postaction={
            decorate,
            decoration={
                markings,
                mark=at position #1 with {
                    \pgfslopedattimefalse % <---
                    \draw (0,0) -- (1,0) node[pos=1.1] {$x$};
                    \draw (0,0) -- (0,1) node[pos=1.1] {$y$};
                }
            }
        }
    }]
    \draw[rotated coordsys at/.list={0.1,0.3,0.5,0.7,0.9}]  (-2,-1) .. controls (0,-2) .. (2,-1);
\end{tikzpicture}
\end{document}

@hmenke
Copy link
Member

hmenke commented Jun 17, 2020

Possible patch, please test.

diff --git a/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.markings.code.tex b/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.markings.code.tex
index 9d18797d..23b7ff67 100644
--- a/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.markings.code.tex
+++ b/tex/generic/pgf/libraries/decorations/pgflibrarydecorations.markings.code.tex
@@ -89,6 +89,7 @@
     \pgfinterruptpath%
       \pgfscope%
         \let\pgf@lib@dec@mark@marks=\pgfutil@empty%
+        \pgfslopedattimefalse
         \pgf@lib@dec@computed@action%
       \endpgfscope%
     \endpgfinterruptpath%

hmenke added a commit to hmenke/pgf that referenced this issue Jun 17, 2020
This can interfere with decorations.markings where now the node option
`sloped' is also inferred implicitly for all nodes.
@hmenke hmenke linked a pull request Jun 17, 2020 that will close this issue
@hmenke hmenke closed this as completed Jun 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

2 participants