绘制除中间区域之外的每个第 n 个点

绘制除中间区域之外的每个第 n 个点

我发现这些小巧的补充这里,但我很难阅读代码:

\makeatletter
\def\pgfplotsutil@decstringcounter#1{%
    \begingroup
        \c@pgf@counta=#1\relax
        \advance\c@pgf@counta by -1
        \edef#1{\the\c@pgf@counta}%
        \pgfmath@smuggleone#1%
    \endgroup
}%

\pgfplotsset{
    /pgfplots/each nth point**/.style 2 args={%
        /pgfplots/x filter/.append code={%
            \ifnum\coordindex=0
                \def\c@pgfplots@eachnthpoint@xfilter{#2}%
                \def\c@pgfplots@eachnthpoint@xfilter@zero{0}%
            \fi
            \ifx\c@pgfplots@eachnthpoint@xfilter@zero\c@pgfplots@eachnthpoint@xfilter
                \def\c@pgfplots@eachnthpoint@xfilter{#1}%
            \else
                \let\pgfmathresult\pgfutil@empty
            \fi
            \pgfplotsutil@decstringcounter\c@pgfplots@eachnthpoint@xfilter
        }%
    },
}

\pgfplotsset{
    /pgfplots/each nth point*/.style 2 args={%
        /pgfplots/x filter/.append code={%
            \ifnum\coordindex=0
                \def\c@pgfplots@eachnthpoint@xfilter{0}%
                \edef\c@pgfplots@eachnthpoint@xfilter@cmp{#1}%
            \else
                \ifnum\coordindex>#2\relax
                    \pgfplotsutil@advancestringcounter\c@pgfplots@eachnthpoint@xfilter
                    \ifx\c@pgfplots@eachnthpoint@xfilter@cmp\c@pgfplots@eachnthpoint@xfilter
                        \def\c@pgfplots@eachnthpoint@xfilter{0}%
                    \else
                        \let\pgfmathresult\pgfutil@empty
                    \fi
                \fi
            \fi
        }%
    },
}
\makeatother

我熟悉和的用法\makeatletter\makeatother也熟悉编程概念,但这种语法总是给我带来麻烦。

  1. 是否each nth point**垂直移动绘制点?

  2. 我知道一般来说,each nth point*在开始时绘制每个点,然后在指定数量的数据点之后开始绘制每个第 n 个点。

    a. 是否先if绘制第一个坐标,然后为其余数据点重新定义一个变量?使用第一个参数?

    b.当到达第二个参数对应的数据点时,第一个if里面的第一个是否会激活?else

    c. 其余代码是否仅来自普通each nth point代码,嵌套else抛出/不绘制到达那里的任何索引的点?

这个练习有一个要点(没有双关语的意思)。我想修改一下every nth point*,让它接受 3 个参数而不是 2 个(我假设/.style 2 args=变成/.style 3 args=),这样它就可以绘制除某个区域(arg2 < x < arg3)之外的每个第 n 个点,在该区域将绘制每个点。

答案1

我为给出的代码添加了一些注释。不过第一部分对我来说有点过度了。它只是一个减少计数器值的函数,参数是一个数字。其他方法也可以轻松实现这一点,但无论如何。

\makeatletter
\def\pgfplotsutil@decstringcounter#1{%
    \begingroup% Standard scoping for the actions
        \c@pgf@counta=#1\relax% Equate the temp TikZ counter to #1
        \advance\c@pgf@counta by -1% Decrease the temp TikZ counter by 1
        \edef#1{\the\c@pgf@counta}%Redefine the argument #1
        \pgfmath@smuggleone#1% Make sure the argument has this meaning after the scope ends.
    \endgroup% End scoping
}%

然后我们有一个稍微复杂一点的

\pgfplotsset{
    /pgfplots/each nth point**/.style 2 args={%A style def that takes 2 arguments
        /pgfplots/x filter/.append code={%Add the following code to the existing key code
            \ifnum\coordindex=0% Obvious! 
% If true define the following two counters as such (but they are not actual TeX counters!)
                \def\c@pgfplots@eachnthpoint@xfilter{#2}%
                \def\c@pgfplots@eachnthpoint@xfilter@zero{0}%
            \fi% End of if
% Here it is again a bit I-wouldn't-do-that code. Compares the values of two "counters".
% What is implemented here is simply taking a Mod(myvalue,n) is zero? op. 
% If yes then Reset the "counter" to n and don't touch \pgfmathresult (point is passed)
% If no empty \pgfmathresult so (point is discarded)
            \ifx\c@pgfplots@eachnthpoint@xfilter@zero\c@pgfplots@eachnthpoint@xfilter
                \def\c@pgfplots@eachnthpoint@xfilter{#1}%
            \else
                \let\pgfmathresult\pgfutil@empty
            \fi
% Decrease the coord count by 1 and done. Hence next the  "obvious" \ifnum is skipped
            \pgfplotsutil@decstringcounter\c@pgfplots@eachnthpoint@xfilter
        }%
    },
}

现在来看看单星版本(我跳过了类似的部分)

\pgfplotsset{
    /pgfplots/each nth point*/.style 2 args={%
        /pgfplots/x filter/.append code={% Same
            \ifnum\coordindex=0% Same 
                \def\c@pgfplots@eachnthpoint@xfilter{0}% Same
                \edef\c@pgfplots@eachnthpoint@xfilter@cmp{#1}% Same
            \else% Same 
                \ifnum\coordindex>#2\relax% If we passed a certain coordinate num
% We don't have the def on the next macro but naming is obvious
% It is very similar to the above but this time the counter is increased from 0 to n
                    \pgfplotsutil@advancestringcounter\c@pgfplots@eachnthpoint@xfilter
% If the comparator value and the actual counter is equal?
                    \ifx\c@pgfplots@eachnthpoint@xfilter@cmp\c@pgfplots@eachnthpoint@xfilter%
% Yes reset the counter and don't touch \pgfmathresult (point is passed)
                        \def\c@pgfplots@eachnthpoint@xfilter{0}%
                    \else    
% No empty and point is discarded
                        \let\pgfmathresult\pgfutil@empty
                    \fi% 
                \fi%
            \fi%
        }%
    },
}
\makeatother

我认为这是一种非常复杂的做事方式。下面是同样的操作,使用您要求的三个参数。您可以删除注释以返回到紧凑版本。

\documentclass{standalone}
\usepackage{pgfplots}
\makeatletter
\pgfplotsset{
my filter/.style args={every#1between#2and#3}{%
/pgfplots/x filter/.append code={%
\ifnum\coordindex<#2%
  % Nothing
\else% Did we pass #3?
  \ifnum\coordindex>#3%
    %Nothing
  \else% Ok filter is on, don't disturb \pgfmathresult for convenience
    \pgfmathsetmacro\temp{int(mod(\coordindex,#1))}%
    \ifnum0=\temp\relax% Are we on the nth point?
      % Yes do nothing let it pass
    \else% discard it
      \let\pgfmathresult\pgfutil@empty
    \fi%
  \fi%
\fi%
}}}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}[my filter=every 50 between 700 and 1000]
% If works properly we should see some ragged part among the smooth part
\addplot[samples=1501] {sin(deg(5*x))};
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容