init: tool for graphing functions and slope fields in love2d
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"runtime.version": "LuaJIT",
|
||||
"workspace.library": ["../love2d"],
|
||||
"runtime.special": {
|
||||
"love.filesystem.load": "loadfile"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
local function getPixelPosition(point, minPoint, maxPoint, drawBounds)
|
||||
if
|
||||
point[1] < minPoint[1]
|
||||
or point[1] > maxPoint[1]
|
||||
or point[2] < minPoint[2]
|
||||
or point[2] > maxPoint[2]
|
||||
then
|
||||
error("Point ("..point[1]..", "..point[2]..") outside the bounds ("
|
||||
..minPoint[1]..", "..minPoint[2]..") to ("..maxPoint[1]..", "..maxPoint[2]..")")
|
||||
end
|
||||
local pointBound = {maxPoint[1] - minPoint[1], maxPoint[2] - minPoint[2]}
|
||||
local pointOffset = {point[1] - minPoint[1], -point[2] - minPoint[2]}
|
||||
local position = {
|
||||
(pointOffset[1] / pointBound[1]) * drawBounds.width + drawBounds.x,
|
||||
(pointOffset[2] / pointBound[2]) * drawBounds.height + drawBounds.y
|
||||
}
|
||||
return position[1], position[2]
|
||||
end
|
||||
|
||||
function GraphFunction(x, y, width, height, func)
|
||||
local points = {}
|
||||
local origin = {x = (width + x) / 2, y = (height + y) / 2}
|
||||
local neg_x, neg_y = -math.floor(origin.x), -math.floor(origin.y)
|
||||
local pos_x, pos_y = math.floor(origin.x), math.floor(origin.y)
|
||||
for i = neg_x, pos_x, 1 do
|
||||
local j = math.floor(func(i))
|
||||
if j > neg_y and j < pos_y then
|
||||
local k, l = getPixelPosition({i,j}, {neg_x,neg_y}, {pos_x,pos_y},
|
||||
{x=x,y=x,width=width,height=height})
|
||||
table.insert(points, k)
|
||||
table.insert(points, l)
|
||||
end
|
||||
end
|
||||
return points
|
||||
end
|
||||
|
||||
function GetLineFromSlope(midpoint, slope, length, color)
|
||||
color = color or {1, 1, 1}
|
||||
local delta_x, delta_y
|
||||
if slope == nil then
|
||||
delta_x, delta_y = 0, length
|
||||
else
|
||||
delta_x = math.sqrt((length ^ 2) / (1 + slope ^ 2))
|
||||
delta_y = -(slope * delta_x)
|
||||
end
|
||||
local x1 = midpoint.x - delta_x / 2
|
||||
local y1 = midpoint.y - delta_y / 2
|
||||
local x2 = x1 + delta_x
|
||||
local y2 = y1 + delta_y
|
||||
return {
|
||||
p1 = {x = x1, y = y1},
|
||||
p2 = {x = x2, y = y2},
|
||||
midpoint = midpoint,
|
||||
color = color
|
||||
}
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
local function factorial(n)
|
||||
if n <= 2 then
|
||||
return n
|
||||
end
|
||||
return n * factorial(n-1)
|
||||
end
|
||||
|
||||
local function calculate_e(terms)
|
||||
local e = 1
|
||||
for i = 1, terms do
|
||||
e = e + 1 / factorial(i)
|
||||
end
|
||||
return e
|
||||
end
|
||||
return calculate_e(10)
|
||||
@@ -0,0 +1,165 @@
|
||||
local utf8 = require("utf8")
|
||||
|
||||
require("coordinates")
|
||||
-- to use with functions involving e
|
||||
--local e = require("eulerNumber")
|
||||
|
||||
local function differential(x, y)
|
||||
return 2*y
|
||||
end
|
||||
|
||||
local function loadWindow()
|
||||
love.window.setTitle("Slope Fields")
|
||||
love.keyboard.setKeyRepeat(true)
|
||||
end
|
||||
love.load = loadWindow
|
||||
|
||||
local function drawLine(line)
|
||||
love.graphics.setColor(unpack(line.color))
|
||||
love.graphics.line(line.p1.x, line.p1.y, line.p2.x, line.p2.y)
|
||||
love.graphics.circle("fill", line.midpoint.x, line.midpoint.y, 4)
|
||||
end
|
||||
|
||||
local width, height = love.window.getMode()
|
||||
|
||||
local boxMargin = 10
|
||||
local boxHeight = math.max(height / 12, 20)
|
||||
local textbox = {
|
||||
x = boxMargin,
|
||||
y = height - (boxHeight + boxMargin),
|
||||
width = width - 2 * boxMargin,
|
||||
height = boxHeight,
|
||||
padding = 5,
|
||||
text = 'x',
|
||||
active = false,
|
||||
colors = {
|
||||
background = {0.2, 0.2, 0.2},
|
||||
text = {0.9, 0.9, 0.9}
|
||||
}
|
||||
}
|
||||
local graphbox = {
|
||||
x = boxMargin,
|
||||
y = boxMargin,
|
||||
width = width - 2 * boxMargin,
|
||||
height = textbox.y - 2 * boxMargin,
|
||||
colors = {
|
||||
background = {0.2, 0.2, 0.2}
|
||||
}
|
||||
}
|
||||
|
||||
local center = {
|
||||
x = graphbox.x + graphbox.width / 2,
|
||||
y = graphbox.y + graphbox.height / 2
|
||||
}
|
||||
local scale = 5
|
||||
local xScale, yScale
|
||||
local step
|
||||
if graphbox.width <= graphbox.height then
|
||||
step = graphbox.width / (2 * (scale+1))
|
||||
xScale = scale
|
||||
yScale = math.floor(graphbox.height / (2 * step)) - 1
|
||||
else
|
||||
step = graphbox.height / (2 * (scale+1))
|
||||
yScale = scale
|
||||
xScale = math.floor(graphbox.width / (2 * step)) - 1
|
||||
end
|
||||
|
||||
local lines = {
|
||||
grid = {},
|
||||
axes = {
|
||||
x = GetLineFromSlope(center, 0, graphbox.width),
|
||||
y = GetLineFromSlope(center, nil, graphbox.height)
|
||||
},
|
||||
field = {}
|
||||
}
|
||||
local xpos, ypos = graphbox.x, graphbox.y + graphbox.height
|
||||
for y = -yScale, yScale, 1 do
|
||||
ypos = ypos - step
|
||||
lines.grid[{y=y}] = GetLineFromSlope({x = center.x, y = ypos}, 0, graphbox.width, {0.3, 0.3, 0.3})
|
||||
end
|
||||
for x = -xScale, xScale, 1 do
|
||||
xpos = xpos + step
|
||||
lines.grid[{x=x}] = GetLineFromSlope({x = xpos, y = center.y}, nil, graphbox.height, {0.3, 0.3, 0.3})
|
||||
ypos = graphbox.y + graphbox.height
|
||||
for y = -yScale, yScale, 1 do
|
||||
ypos = ypos - step
|
||||
lines.field[{x, y}] = GetLineFromSlope({x = xpos, y = ypos}, differential(x,y), 50, {0, 0.5, 1})
|
||||
end
|
||||
end
|
||||
|
||||
local function func(x)
|
||||
return x^2
|
||||
end
|
||||
local points = GraphFunction(graphbox.x, graphbox.y, graphbox.width, graphbox.height, func)
|
||||
|
||||
local function drawScene()
|
||||
love.graphics.setColor(unpack(graphbox.colors.background))
|
||||
love.graphics.rectangle('fill',
|
||||
graphbox.x, graphbox.y,
|
||||
graphbox.width, graphbox.height,
|
||||
4, 4)
|
||||
|
||||
love.graphics.setColor(unpack(textbox.colors.background))
|
||||
love.graphics.rectangle('fill',
|
||||
textbox.x, textbox.y,
|
||||
textbox.width, textbox.height,
|
||||
4, 4)
|
||||
|
||||
love.graphics.setColor(unpack(textbox.colors.text))
|
||||
love.graphics.printf(textbox.text,
|
||||
textbox.x + textbox.padding, textbox.y + textbox.padding,
|
||||
textbox.width, 'left', 0, 2, 2)
|
||||
|
||||
for _, line in pairs(lines.grid) do
|
||||
drawLine(line)
|
||||
end
|
||||
for _, line in pairs(lines.axes) do
|
||||
drawLine(line)
|
||||
end
|
||||
for _, line in pairs(lines.field) do
|
||||
drawLine(line)
|
||||
end
|
||||
|
||||
if points ~= nil then
|
||||
love.graphics.setColor(0,1,0)
|
||||
love.graphics.points(points)
|
||||
end
|
||||
end
|
||||
love.draw = drawScene
|
||||
|
||||
local function textboxinput(text)
|
||||
if textbox.active and string.match(text,"[xy+%-%/*%^%d()]") then
|
||||
textbox.text = textbox.text .. text
|
||||
end
|
||||
end
|
||||
love.textinput = textboxinput
|
||||
|
||||
local function keypress(key)
|
||||
if key == "backspace" then
|
||||
local byteoffset = utf8.offset(textbox.text, -1)
|
||||
|
||||
if byteoffset then
|
||||
textbox.text = string.sub(textbox.text, 1, byteoffset - 1)
|
||||
end
|
||||
return
|
||||
end
|
||||
if key == "return" then
|
||||
textbox.active = false
|
||||
end
|
||||
end
|
||||
love.keypressed = keypress
|
||||
|
||||
local function mousepress(x, y)
|
||||
if
|
||||
x >= textbox.x and
|
||||
x <= textbox.x + textbox.width and
|
||||
y >= textbox.y and
|
||||
y <= textbox.y + textbox.height
|
||||
then
|
||||
textbox.active = true
|
||||
elseif textbox.active then
|
||||
textbox.active = false
|
||||
end
|
||||
end
|
||||
love.mousepressed = mousepress
|
||||
|
||||
Reference in New Issue
Block a user