Lua error at line 8: 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 8: Missing 'Functions'.
local p = {}
local Expression = require("Module:ColinTheCat/Expression")
function p.Plot2D(frame)
local fig = mw.html.create("div")
assert(frame.args.Functions, "Missing 'Functions'")
assert(frame.args.To, "Missing 'To'")
local options = {
functions = mw.text.jsonDecode(frame.args.Functions),
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 = mw.html.create()
draw_grid(svg, options)
fig:callParserFunction("#tag:svg", tostring(svg), {
string.format("viewBox=%s %s %s %s", options.from.x, options.from.y, options.to.x, options.to.y),
"style=width: 100%; stroke-width: 0.01px;",
})
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_y.."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_y.."V"..height
k = k - step_x
end
-- +y
k = options.origin.y + step_y
while(k < options.to.y) do
path = path.."M"..min_x.." "..k.."H"..width
k = k + step_x
end
-- -y
k = options.origin.y - step_y
while(k > options.to.y) do
path = path.."M"..min_x.." "..k.."H"..width
k = k - step_x
end
svg:tag("path")
:attr("fill", "#0000")
:attr("stroke", "#666")
:attr("d", path)
:done()
end
local ExprBaseCtx = {}
function ExprBaseCtx:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function ExprBaseCtx:lookup(name)
return self.vars and self.bars[name] or math[name] or error("Unknown variable: "..name)
end
function parse_expr(expr)
local tok = Expression.Tokenizer:new{str=expr}
local expr = Expression.parse_expr(tok)
if not expr then error("Invalid expression: "..expr) end
if Tokenizer:peek() then error("Leftover tokens: "..tok.str) end
return expr
end
function translate_point(options, x, y)
return x, options.to.y-y
end
return p