addplot 调用中的总和

addplot 调用中的总和

在回应这个帖子我想知道是否可以编写循环里面 addplot调用。我实际上指的是循环内部addplot,而不是循环addplot内部for(只是为了让自己清楚)。

我对这篇文章的回答涉及绘制多个函数,这些函数是给定频率的谐波的总和,这会产生多个addplot仅在总和的一个项上不同的调用。

\addplot {sin(4*0.5*\x r)/0.5};    
\addplot {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5};
\addplot {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5};
\addplot {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5};
\addplot {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5 + sin(4*4.5*\x r)/4.5};
\addplot {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5 + sin(4*4.5*\x r)/4.5 + sin(4*5.5*\x r)/5.5};

我觉得这不是很优雅,我想知道是否有办法避免这种情况,使用类似

\addplot {sum[nmin,nmax,n](sin(\n*0.5*\x r)/0.5)};

其中nmin/nmax是总和的起始/终止索引。这个问题可以推广到乘积或其他 for 循环。

以下是测试此问题的 MWE

\documentclass[tikz,border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{cycle list/Reds-6}

\begin{document}

\begin{tikzpicture}
\begin{axis}[%
    width=\textwidth,
    axis x line=bottom,
    axis y line=left,cycle multi list={Reds-6}]
    \addplot+[samples=300,smooth] {sin(4*0.5*\x r)/0.5};    
    \addplot+[samples=300,smooth] {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5};
    \addplot+[samples=300,smooth] {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5};
    \addplot+[samples=300,smooth] {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5};
    \addplot+[samples=300,smooth] {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5 + sin(4*4.5*\x r)/4.5};
    \addplot+[samples=300,smooth] {sin(4*0.5*\x r)/0.5 + sin(4*1.5*\x r)/1.5 + sin(4*2.5*\x r)/2.5 + sin(4*3.5*\x r)/3.5 + sin(4*4.5*\x r)/4.5 + sin(4*5.5*\x r)/5.5};
\end{axis}
\end{tikzpicture}
\end{document}

答案1

我设置了一个模板,并用它来listofitems解析它?

\readlist\termstencil{sin(4*?.5*\x r)/?.5}

?然后,在每次循环中用替换的值0,然后1,...,5。必须进行一些检查以确保不在+第一个术语之前添加 ,等等。将生成的标记收集到宏 中\myeqn,然后将其传递给\addplot

\documentclass[tikz,border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{cycle list/Reds-6}
\usepackage{listofitems}
\makeatletter
\newcommand\loopthroughterm[1]{%
  \def\myeqn{}%
  \foreach\z in{0,...,#1}{%
    \ifnum\z=0\relax\else\g@addto@macro\myeqn{+}\fi%
    \foreachitem\zz\in\termstencil[]{%
      \ifnum\zzcnt=1\else%
        \expandafter\g@addto@macro\expandafter\myeqn\expandafter{\z}\fi%
      \expandafter\g@addto@macro\expandafter\myeqn\expandafter{\zz}%
    }%
  }%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}[%
    width=\textwidth,
    axis x line=bottom,
    axis y line=left,cycle multi list={Reds-6}]
    \setsepchar{?}
    \readlist\termstencil{sin(4*?.5*\x r)/?.5}
    \foreach\k in{0,...,5}{
      \loopthroughterm{\k}
      \addplot+[samples=300,smooth] {\myeqn};
    }
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

退出后tikzpicture,可以\detokenize\expandafter{\myeqn}确认用于最终循环索引的令牌本身:

在此处输入图片描述


附录

看到 jbfu 使用了辅助宏,我意识到我可以使用相同的概念来省去这种listofitems方法,而不是使用另一个包来代替它。

基本上,我让\loopthroughterm宏创建一系列形式为 的标记\termstencil{0}+\termstencil{1}+\termstencil{2}...。然后,只要\termstencil用户正确定义 ,在本例中为

\def\termstencil#1{sin(4*#1.5*\x r)/#1.5}

那么最终一切都会顺利。

\documentclass[tikz,border=10pt]{standalone}
\usepackage{pgfplots}
\usepackage[T1]{fontenc}
\pgfplotsset{compat=1.5}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{cycle list/Reds-6}
\makeatletter
\newcommand\loopthroughterm[1]{%
  \def\myeqn{}%
  \foreach\z in{0,...,#1}{%
    \ifnum\z=0\relax\else\g@addto@macro\myeqn{+}\fi%
    \expandafter\g@addto@macro\expandafter\myeqn\expandafter{%
      \expandafter\termstencil\expandafter{\z}}%
  }%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{axis}[%
    width=\textwidth,
    axis x line=bottom,
    axis y line=left,cycle multi list={Reds-6}]
    \def\termstencil#1{sin(4*#1.5*\x r)/#1.5}
    \foreach\k in{0,...,5}{
      \loopthroughterm{\k}
      \addplot+[samples=300,smooth] {\myeqn};
    }
\end{axis}
\end{tikzpicture}
\end{document}

情节与之前的代码相同,但是去标记化的形式\myeqn现在是这样的:

在此处输入图片描述

此外,使用几个额外的\expandafters,形式为

\newcommand\loopthroughterm[1]{%
  \def\myeqn{}%
  \foreach\z in{0,...,#1}{%
    \ifnum\z=0\relax\else\g@addto@macro\myeqn{+}\fi%
    \expandafter\expandafter\expandafter\g@addto@macro\expandafter%
      \expandafter\expandafter\myeqn\expandafter\expandafter\expandafter{%
        \expandafter\termstencil\expandafter{\z}}%
  }%
}

最终版本\myeqn包含实际需要的 token:

在此处输入图片描述

答案2

这里是带有的xinttools。我怀疑(但没有检查)不可扩展循环不能在\addplot参数内部使用,因此我定义了初步宏\myterm以与可扩展实用程序\xintApply和一起使用\xintListWithSep

外部\xintFor是不可扩展的,并且免除了我们任何初步的宏定义。

\documentclass[tikz,border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5}
\usepgfplotslibrary{colorbrewer}
\pgfplotsset{cycle list/Reds-6}
\usepackage{xinttools}
\begin{document}

\begin{tikzpicture}
\def\myterm#1{sin(4*#1.5*\x r)/#1.5}
\begin{axis}[%
    width=\textwidth,
    axis x line=bottom,
    axis y line=left,cycle multi list={Reds-6}]
    \xintFor #1 in {0, 1, 2, 3, 4, 5} \do 
    {%    
    \addplot+[samples=300,smooth] 
     {\xintListWithSep{+}{\xintApply\myterm{\xintSeq{0}{#1}}}}; 
    }   
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容