我试图通过逐步展示曲线的创建方式来可视化 B 样条函数的构造。这涉及绘制类似以下的曲线:
我尝试将 t0 到 t5 定义为一个列表\def\tvalues{{53,125,172,248,286,338,415}}
,并创建 N_i^1(t) 作为我可以调用的函数:
\pgfmathdeclarefunction{bsplinebase}{}{\pgfmathparse{(and(#1>=\tvalues[#2], #1<\tvalues[#2+1]))}
效果不太好。问题似乎出在列表访问上,所以我尝试按照描述的方式重建它这里:
\pgfmathdeclarefunction{bsplinebase}{2}{
\begingroup
\pgfmathparse{#2}
\edef\arrayvalue{\pgfmathresult}
\pgfmathparse{\tvalues[\arrayvalue]}
\edef\lowvalue{\pgfmathresult}
\pgfmathparse{#2+1}
\edef\brrayvalue{\pgfmathresult}
\pgfmathparse{\tvalues[\brrayvalue]}
\edef\highvalue{\pgfmathresult}
\pgfmathparse{(and(#1>=\lowvalue, #1<\highvalue))}%
\endgroup
}
测试抽奖:
\pgfplotsset{ymax=1, ymin=0, xmin=0, xmax=500}
\begin{tikzpicture}[samples=1000,scale=0.5]
\begin{axis}[xlabel=$x$,ylabel=$y$]
\addplot [mark=none] {bsplinebase(x, 3)};
\addplot [mark=none] {bsplinebase(x, 4)};
\end{axis}
\end{tikzpicture}
不管怎样,我File ended while scanning use of \pgfflt@readlowlevelfloat.
每次都得到了。
我没有任何想法。如何使用给定的一组 t 值实现类似于上面的可视化并显示 N_i^k ?
(图片来源:我校计算机图形学讲座材料)
编辑:我根据 Christian 的回答修改了我的解决方案,它适用于基本函数。下一步是让递归调用工作。所以我这样做了:
\def\tvalues{{53,125,172,248,286,338,415}}
% N_i^1(t), param 1: t, param 2: i
\pgfmathdeclarefunction{bsplinebase}{2}{\pgfmathparse{and(#1>=\tvalues[#2], #1<\tvalues[#2+1])}}
% N_i^k(t), param 1: t, param 2: i, param 3: k with k > 1
\pgfmathdeclarefunction{bsplinehigh}{3}{ %
\pgfmathparse{ %
((#1-\tvalues[#2])/(\tvalues[#2+#3-1]-\tvalues[#2]))*bspline(#1,#2,#3-1)+((\tvalues[#2+#3]-#1)/(\tvalues[#2+#3]-\tvalues[#2+1]))*bspline(#1,#2+1,#3-1)%
}
}
% N_i^k(t), param 1: t, param 2: i, param 3: k
\pgfmathdeclarefunction{bspline}{3}{\pgfmathparse{ifthenelse(#3 <= 1, bsplinebase(#1, #2), bsplinehigh(#1, #2, #3))}}
调用基本相同(\addplot [mark=none] {bspline(x, 3, 1)};
对于 x、4、1 也一样),因此它应该只使用 bsplinebase 函数,因为第三个参数应该让 ifthenelse 使用第一个选择,即 bsplinebase,而不是 bsplinehigh。
我还尝试bsplinehigh
用常数替换 -logic,在这种情况下它成功构建了 pdf,但没有图,甚至没有轴。
显示的第一个错误Package PGF Math Error: You've asked me to divide '-247.0' by '0.0', but I ca{53,125,172,248,286,338,415}[3+1]))*bspline(1,3+1,1-1)'). \addplot [mark=none] {bspline(x,3,1)};
似乎已经损坏。此外,他甚至不应该陷入必须进行划分的情况,如上所述。
为什么这不起作用?它应该与以前完全相同,但 ifthenelse 不能按预期工作。我唯一的猜测是,即使没有使用 else-case,它也会得到评估,但我不确定这是否真的如此。如果是的话,我需要一种方法来防止这种情况。
编辑:这个问题暗示可能正如我猜测的那样。
阅读上述问题的答案后,我尝试像这样解决评估问题:
\def\tvalues{{53,125,172,248,286,338,415}}
% N_i^1(t), param 1: t, param 2: i
\pgfmathdeclarefunction{bsplinebase}{2}{\pgfmathparse{and(#1>=\tvalues[#2], #1<\tvalues[#2+1])}}
% N_i^k(t), param 1: t, param 2: i, param 3: k with k > 1
\pgfmathdeclarefunction{bsplinehigh}{3}{%
\pgfmathparse{%
(((#1-\tvalues[#2])/(\tvalues[#2+#3-1]-\tvalues[#2]))*bspline(#1,#2,#3-1)+((\tvalues[#2+#3]-#1)/(\tvalues[#2+#3]-\tvalues[#2+1]))*bspline(#1,#2+1,#3-1))%
}
}
% N_i^k(t), param 1: t, param 2: i, param 3: k
\pgfmathdeclarefunction{bspline}{3}{%
\ifnum#3<2\pgfmathparse{bsplinebase(#1,#2)}\else\pgfmathparse{bsplinehigh(#1,#2,#3)}\fi%
}
这再次适用于我的 basespline 案例,所以现在我添加了\addplot [mark=none] {bspline(x,0,2)};
。然后,下一个问题:
Missing = inserted for \ifnum. \addplot [mark=none] {bspline(x,0,2)};
我不知道问题是什么。
编辑:这个问题有同样的问题,现在我们越来越接近了!
答案1
主要困难似乎是 TeX 浮点单元的弱点 —— 它似乎无法处理数组语法。通过有效方法停用它use fpu=false
。
请注意,您的代码不包含任何domain
参数——您的x
参数是使用默认域采样的-5:5
。
添加两者+一些样式更改(我在试验代码片段时忘记删除了)会导致
\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\begin{document}
\def\tvalues{{53,125,172,248,286,338,415}}
\pgfmathdeclarefunction{bsplinebase}{2}{\pgfmathparse{and(#1>=\tvalues[#2], #1<\tvalues[#2+1])}}
\begin{tikzpicture}[samples=1000]
\begin{axis}[
use fpu=false,
xlabel=$x$,ylabel=$y$,
ymax=2, ymin=0, xmin=0, xmax=500,
domain=0:500,
]
\addplot [mark=none] {bsplinebase(x, 3)};
\addplot [mark=none] {bsplinebase(x, 4)};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
在 Christian 的帮助和大量的搜索下,我成功让它工作了!
定义:
\def\tvalues{{53,125,172,248,286,338,415}}
% N_i^1(t), param 1: t, param 2: i
\pgfmathdeclarefunction{bsplinebase}{2}{\pgfmathparse{and(#1>=\tvalues[#2], #1<\tvalues[#2+1])}}
% N_i^k(t), param 1: t, param 2: i, param 3: k with k > 1
\pgfmathdeclarefunction{bsplinehigh}{3}{%
\pgfmathparse{%
(((#1-\tvalues[#2])/(\tvalues[#2+#3-1]-\tvalues[#2]))*bspline(#1,#2,#3-1)+((\tvalues[#2+#3]-#1)/(\tvalues[#2+#3]-\tvalues[#2+1]))*bspline(#1,#2+1,#3-1))%
}
}
% N_i^k(t), param 1: t, param 2: i, param 3: k
\pgfmathdeclarefunction{bspline}{3}{%
\pgfmathparse{#3>1 ? 0 : 1}%
\ifnum\pgfmathresult=1\pgfmathparse{bsplinebase(#1,#2)}\else\pgfmathparse{bsplinehigh(#1,#2,#3)}\fi%
}
然后呼叫:
\pgfplotsset{ymax=2, ymin=0, xmin=1,xmax=500}
\begin{tikzpicture}[samples=1000]
\begin{axis}[
use fpu=false,
xlabel=$x$,ylabel=$y$,
ymax=2, ymin=0, xmin=1, xmax=500,
domain=1:500,
]
\addplot [mark=none] {bspline(x,3,1)};
\addplot [mark=none] {bspline(x,4,1)};
\addplot [mark=none] {bspline(x,0,2)};
\addplot [mark=none] {bspline(x,4,2)};
\addplot [mark=none] {bspline(x,1,3)};
\end{axis}
\end{tikzpicture}