Lua error at line 34: Missing 'Functions'.
Arguments
Argument | Description | Example | Default |
---|---|---|---|
Plots | Plots as JSON | See #Example | |
From | Lowest x,y to plot | -pi/2,0 |
0,0
|
To | Highest x,y to plot | 10^2,2 |
|
Origin | X/Y Axis origin | 0.5,0.5 |
0,0
|
GridStep | Coordinate grid step size | pi/2,1 |
1,1
|
Inline | Display the plot inline instead of floating | true |
(absent) |
Axis label (not implemented) | |||
LabelStepX | Label for grid X-axis increments | format("%sπ", dfrac(x/pi, 1)) |
format("%d", x)
|
LabelStepY | Label for grid X-axis increments | format("%.1f", y) |
format("%d", x)
|
ColorX | X-axis color | #44f |
#f44
|
ColorY | Y-axis color | #0f4 |
#0f0
|
Underlined Arguments are required.
Available Functions and Constants in Expressions
printf(format, ...args)
See Lua string.format.dfrac(number, is_factor)
Formats a float as a fraction, if possible. If it is a factor, then the number 1 or -1 will only produce its sign as an output, useful when formatting as a factor of pi, for example. See #Example below.sin,floor,abs,...
Any constant or function from the Lua math library can be used directly (without themath.
prefix).
Example
{{#invoke:ColinTheCat/Plotter|Plot2D |From=-0.2, -1.2 |To=2 * pi + 0.2, 1.2 |GridStep=0.5 * pi, 1 |LabelStepX=format("%sπ", dfrac(x/pi, 1)) |Plots= [ {"Type": "function", "Function": "sin(x)", "Samples": 100, "Label": "sin"}, {"Type": "function", "Function": "cos(x)", "Samples": 100, "Label": "cos"}, {"Type": "function", "Function": "tan(x)", "Samples": 35, "Label": "tan", "Ranges": [ {"To": "(0.5-0.2)*pi"}, {"From": "(0.5+0.2)*pi", "To": "(1.5-0.2)*pi"}, {"From": "(1.5+0.2)*pi"} ]} ] }}
Lua error at line 34: Missing 'Functions'.
local p = {}
local functions = {
["x^2"] = function(x) return x*x end,
sin = math.sin,
cos = math.cos,
tan = math.tan,
asin = math.asin,
acos = math.acos,
atan = math.atan,
sinh = math.sinh,
cosh = math.cosh,
tanh = math.tanh,
exp = math.exp,
}
local constants = {
["1"] = 1,
pi = math.pi,
tau = 2 * math.pi,
e = math.exp(1),
deg = math.deg(1),
}
function p.Plot2D(frame)
local fig = mw.html.create("figure")
:attr("class", "mw-default-size mw-halign-none")
if frame.args.Caption then
fig:tag("figcaption")
:wikitext(frame.args.Caption)
end
assert(frame.args.Functions, "Missing 'Functions'")
assert(frame.args.To, "Missing 'To'")
local options = {
functions = mw.text.jsonDecode(frame.args.Functions),
aspect = parse_aspect(frame.args.Aspect or "4:3"),
from = parse_xy(frame.args.From or "0 0"),
to = parse_xy(frame.args.to),
origin = parse_xy(frame.args.Origin or "0 0"),
grid_step = { x=frame.args.GridStepX or 1, y=frame.args.GridStepY or 1 }
}
local svg = fig:tag("svg")
:cssText("width: 100%; aspect-ratio: "..options.aspect)
:attr("width", options.to.x - options.from.x)
:attr("height", options.to.y - options.from.y)
:attr("viewBox", string.format("%s %s %s %s", options.from.x, options.from.y, options.to.x, options.to.y))
draw_grid(svg, options)
return tostring(fig)
end
function parse_aspect(str)
local i = str:find(":", 1, false)
if i == nil then return tonumber(str) end
local y = tonumber(str:sub(1, i - 1))
local x = tonumber(str:sub(i + 1))
return x/y
end
function parse_xy(str)
local i = str:find(" ", 1, false)
if i == nil then error("Invalid xy: "..str) end
local x = tonumber(str:sub(1, i - 1))
local y = tonumber(str:sub(i + 1))
return { x=x, y=y }
end
function draw_grid(svg, options)
local step_x = eval_math_expr(options.grid_step.x)
local step_y = eval_math_expr(options.grid_step.y)
if step_x <= 0 then error("Invalid x step size") end
if step_y <= 0 then error("Invalid y step size") end
local min_x = options.from.x
local min_y = options.from.y
local width = options.to.x - options.from.x
local height = options.to.y - options.from.y
local path = ""
local k, op
-- +x
k = options.origin.x + step_x
while(k < options.to.x) do
path = path.."M"..k.." "..min_x.."V"..height
k = k + step_x
end
-- -x
k = options.origin.x - step_x
while(k > options.from.x) do
path = path.."M"..k.." "..min_x.."V"..height
k = k - step_x
end
svg:tag("path")
:attr("fill", "#0000")
:attr("stroke", "#666")
:attr("d", path)
:done()
end
function eval_math_expr(expr, x)
local fact = expr:match("^%s*(%d+)")
if fact then
fact = fact..(expr:sub(#fact+1):match("%.%d+") or "")
end
local const = expr:sub(fact and #fact+1 or 1):match("^%s*(.-)%s*$")
fact = fact and tonumber(fact)
local func = functions[const]
const = func and func(x or 0) or constants[const]
if fact == nil and const == nil then error("Invalid expression: "..expr) end
return (fact or 1) * (const or 1)
end
function translate_point(options, x, y)
return x, options.to.y-y
end
return p