我发现这些小巧的补充这里,但我很难阅读代码:
\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
也熟悉编程概念,但这种语法总是给我带来麻烦。
是否
each nth point**
垂直移动绘制点?我知道一般来说,
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}