是否可以使用 mpgraph(可能使用 lua、mplib)绘制标准函数图?例如 gdraw(sin(x)+cos(x))、gdraw(2x+3) 以及一般的 gdraw(f(x)),其中 f(x) 是标准函数的有限组合?
答案1
这个问题似乎是将 Lua 函数与 mplib 和 mpgraph 结合使用
您可以简单地从宏参数构建想要绘制的函数。
\documentclass{article}
\usepackage{luamplib}
\directlua{userdata = userdata or {}}
\begin{document}
\def\plot#1{%
\directlua{
function userdata.f(x)
local _ENV = math
return (#1)
end
luamplib.process_mplibcode([[
vardef f primary x =
runscript("mp.print(userdata.f(" & decimal x & "))")
enddef ;
input graph ;
beginfig(0)
draw begingraph(5cm,3cm)
gdraw (0,f(0)) for x = 1 upto 1000: .. (x/100, f(x/100)) endfor ;
endgraph ;
endfig ;
]])}%
}
\plot{sin(x) + cos(x)}
\plot{sin(2*pi*x) * exp(-x/2)}
\end{document}
通过一点点额外的工作,您还可以获得密钥和值来配置情节。
\documentclass{article}
\usepackage{luamplib}
\usepackage{luacode}
\begin{luacode*}
userdata = userdata or {}
userdata.mplibcode = [[
vardef f primary x =
runscript("mp.print(userdata.f(" & decimal x & "))")
enddef ;
numeric xmin, xmax, samples, width ,height ;
xmin := runscript("mp.print(userdata.xmin)");
xmax := runscript("mp.print(userdata.xmax)");
samples := runscript("mp.print(userdata.samples)");
width := runscript("mp.print(userdata.width)");
height := runscript("mp.print(userdata.height)");
input graph ;
beginfig(0)
draw begingraph(width,height)
gdraw (xmin,f(xmin)) for i = 1 upto samples:
-- ((xmax - xmin) / samples * i + xmin, f((xmax - xmin) / samples * i + xmin))
endfor ;
endgraph ;
endfig ;
]]
function userdata.graph(settings)
settings = settings or {}
userdata.xmin = tostring(settings.xmin or "0")
userdata.xmax = tostring(settings.xmax or "1")
userdata.samples = tostring(settings.samples or "100")
userdata.width = tostring(settings.width or "5cm")
userdata.height = tostring(settings.height or "3cm")
luamplib.process_mplibcode(userdata.mplibcode)
end
\end{luacode*}
\newcommand\plot[2][]{%
\directlua{
local userdata = userdata
local _ENV = math
function userdata.f(x)
return (#2)
end
userdata.graph({#1})
}%
}
\begin{document}
\plot[xmin=-pi,xmax=pi,width="7cm"]{sin(x) + cos(x)}
% ^^^^^
% need to be quoted because this is parsed by Lua
\plot[xmin=0,xmax=10,samples=1000]{sin(2*pi*x) * exp(-x/2)}
\end{document}
\documentclass{article}
\usepackage{pgffor}
\usepackage{luamplib}
\usepackage{luacode}
\begin{luacode*}
userdata = userdata or {}
userdata.mplibcode = [[
color clr ;
numeric Nf, rmin, rmax, xmin, xmax, ymin, ymax, samples, width ,height ;
Nf := runscript("mp.print(#userdata.f)");
rmin := runscript("mp.print(userdata.range[1])");
rmax := runscript("mp.print(userdata.range[2])");
xmin := runscript("mp.print(userdata.xmin)");
xmax := runscript("mp.print(userdata.xmax)");
ymin := runscript("mp.print(userdata.ymin)");
ymax := runscript("mp.print(userdata.ymax)");
samples := runscript("mp.print(userdata.samples)");
width := runscript("mp.print(userdata.width)");
height := runscript("mp.print(userdata.height)");
input graph ;
beginfig(0)
draw begingraph(width,height)
setrange(xmin, ymin, xmax, ymax) ;
for n = 1 upto Nf:
vardef f primary x =
runscript("mp.print(userdata.f[" & decimal n & "](" & decimal x & "))")
enddef ;
clr := runscript("mp.print(userdata.color[" & decimal n & "] or 'black')") ;
drawoptions(runscript("mp.print(userdata.style[" & decimal n & "] or '')")) ;
gdraw (rmin,f(rmin)) for i = 1 upto samples:
-- ((rmax - rmin) / samples * i + rmin, f((rmax - rmin) / samples * i + rmin))
endfor withcolor clr ;
drawoptions() ;
endfor ;
endgraph ;
endfig ;
]]
function userdata.graph(settings)
settings = settings or {}
settings.range = settings.range or {}
userdata.range = {
tostring(settings.range[1] or "0"),
tostring(settings.range[2] or "1")
}
userdata.xmin = tostring(settings.xmin or "0")
userdata.xmax = tostring(settings.xmax or "1")
userdata.ymin = tostring(settings.ymin or "whatever")
userdata.ymax = tostring(settings.ymax or "whatever")
userdata.samples = tostring(settings.samples or "100")
userdata.width = tostring(settings.width or "5cm")
userdata.height = tostring(settings.height or "3cm")
userdata.color = settings.color or {}
userdata.style = settings.style or {}
luamplib.process_mplibcode(userdata.mplibcode)
end
\end{luacode*}
\newcommand\plot[2][]{%
\directlua{userdata.f = {}}%
\foreach \f [count=\i] in {#2} {%
\directlua{
local userdata = userdata
local _ENV = math
userdata.f[\i] = function(x)
return (\f)
end
}%
}%
\directlua{
local userdata = userdata
local _ENV = math
userdata.graph({#1})
}%
}
\begin{document}
\plot[
range={ 0, 10 },
xmin=-1, xmax=11,
ymin=-sqrt(2), ymax=sqrt(2),
samples=1000,
color={ "red", "blue", "(0,.8,.1)" },
style={ "", "dashed evenly", "dashed withdots" }
]{sin(2*pi*x) * exp(-x/2), exp(-x/2), sin(2*pi*x)}
\end{document}
\documentclass{article}
\usepackage{luamplib}
\usepackage{luacode}
\begin{luacode*}
userdata = userdata or {}
userdata.mplibcode = [[
numeric Nf, xmin, xmax, ymin, ymax, width ,height ;
Nf := runscript("mp.print(#userdata.functions)");
xmin := runscript("mp.print(userdata.axis.xmin)");
xmax := runscript("mp.print(userdata.axis.xmax)");
ymin := runscript("mp.print(userdata.axis.ymin)");
ymax := runscript("mp.print(userdata.axis.ymax)");
width := runscript("mp.print(userdata.axis.width)");
height := runscript("mp.print(userdata.axis.height)");
input graph ;
beginfig(0)
draw begingraph(width,height)
setrange(xmin, ymin, xmax, ymax) ;
for n = 1 upto Nf:
vardef f primary x =
runscript("mp.print(userdata.functions[" & decimal n & "].f(" & decimal x & "))")
enddef ;
numeric rmin, rmax, samples ;
rmin := runscript("mp.print(userdata.functions[" & decimal n & "].range[1] or userdata.axis.range[1])");
rmax := runscript("mp.print(userdata.functions[" & decimal n & "].range[2] or userdata.axis.range[2])");
samples := runscript("mp.print(userdata.functions[" & decimal n & "].samples or userdata.axis.samples)");
color clr ;
clr := runscript("mp.print(userdata.functions[" & decimal n & "].color or userdata.axis.color)") ;
drawoptions(runscript("mp.print(userdata.functions[" & decimal n & "].style or userdata.axis.style)")) ;
gdraw (rmin,f(rmin)) for i = 1 upto samples:
-- ((rmax - rmin) / samples * i + rmin, f((rmax - rmin) / samples * i + rmin))
endfor withcolor clr ;
drawoptions() ;
endfor ;
endgraph ;
endfig ;
]]
function userdata.draw_graph()
local axis = userdata.axis
axis.range = {
tostring(axis.range[1] or "0"),
tostring(axis.range[2] or "1")
}
axis.xmin = tostring(axis.xmin or "whatever")
axis.xmax = tostring(axis.xmax or "whatever")
axis.ymin = tostring(axis.ymin or "whatever")
axis.ymax = tostring(axis.ymax or "whatever")
axis.samples = tostring(axis.samples or "100")
axis.width = tostring(axis.width or "5cm")
axis.height = tostring(axis.height or "3cm")
axis.color = tostring(axis.color or "black")
axis.style = tostring(axis.style or "")
luamplib.process_mplibcode(userdata.mplibcode)
end
\end{luacode*}
\newenvironment{luamplibplots}[1][]%
{\directlua{
local userdata = userdata
local _ENV = math
userdata.functions = {}
userdata.axis = {#1}
}}%
{\directlua{userdata.draw_graph()}}
\newcommand\addplot[2][]{%
\directlua{
local userdata = userdata
local tableinsert = table.insert
local _ENV = math
tableinsert(userdata.functions, {
f = function(x) return (#2) end,
range = {},
#1
})
}%
}
\begin{document}
\begin{luamplibplots}
[range={0,10},
xmin=-1,
xmax=11,
ymin=-sqrt(2),
ymax=sqrt(2),
samples=1000]
\addplot[color="red", samples=50]{sin(2*pi*x) * exp(-x/2)}
\addplot[color="blue", style="dashed evenly"]{exp(-x/2)}
\addplot[color="(0,.8,.1)", style="scaled 2pt dashed withdots"]{sin(2*pi*x)}
\addplot[range={exp(-2),exp(2)}]{log(x)}
\end{luamplibplots}
\end{document}