1
0
lissajous-table/main.lua

215 lines
5.2 KiB
Lua

-- NEEDS OPTIMIZATIONS
local angle = 0
local relativeGap = 0.5
local relativeMarker = 0.1
local relativeWidth = 0.08
local rows, cols, circles, curves, markerSize, gap
local opacity = 0.3
local constants = {
circleRadius = 20,
speed = 1,
drawLines = false,
colors = true,
drawMarkers = true,
drawCircles = true,
drawTable = true
}
function HSV(h, s, v, a)
if s <= 0 then return v,v,v end
h, s, v = h/256*6, s/255, v/255
local c = v*s
local x = (1-math.abs((h%2)-1))*c
local m,r,g,b = (v-c), 0,0,0
if h < 1 then r,g,b = c,x,0
elseif h < 2 then r,g,b = x,c,0
elseif h < 3 then r,g,b = 0,c,x
elseif h < 4 then r,g,b = 0,x,c
elseif h < 5 then r,g,b = x,0,c
else r,g,b = c,0,x
end return (r+m),(g+m),(b+m), a or 1
end
function addColors(h1, h2)
local r1, g1, b1, a1 = HSV(h2, 255, 255)
local r2, g2, b2, a2 = HSV(h1, 255, 255)
return (r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2
end
local function distance(x1,y1,x2,y2)
return ((x1-x2)^2 + (y1-y2)^2)^0.5
end
function Curve()
local self = {}
self._points = {}
self.draw = function(self)
if #self._points >= 4 then
love.graphics.line(self._points)
end
end
self.addPoint = function(self, x, y)
table.insert(self._points, x)
table.insert(self._points, y)
end
self.clear = function(self)
self._points = {}
end
return self
end
function genTable(default, N)
local t = {}
for i=0, N-1 do
if type(default) == "function" then
t[i] = default()
else
t[i] = default
end
end
return t
end
function roundDown(X)
return X - (X / 10)
end
function recalc(w, h)
local realSize = (relativeGap + 1) * constants.circleRadius
local rows = roundDown(w / realSize)
local cols = roundDown(h / realSize)
circles = genTable(angle, math.max(rows, cols))
curves = {}
for i=0, rows-1 do
curves[i] = genTable(Curve, cols)
end
end
function love.load(args, unfilteredArgs)
for i=1,#args do
for name in pairs(constants) do
if "-"..name == args[i] then
if type(constants[name]) == "boolean" then
constants[name] = args[i+1] == "true"
elseif type(constants[name]) == "number" then
constants[name] = tonumber(args[i+1])
end
i = i + 1
break
end
end
end
markerSize = constants.circleRadius*relativeMarker
gap = constants.circleRadius*(1+relativeGap)
recalc(love.graphics.getDimensions())
end
function love.update(dt)
angle = angle + constants.speed * dt
for i in pairs(circles) do
circles[i] = angle * (i+1)
end
if angle > math.pi*2 then
angle = angle % math.pi*2
for _, j in pairs(curves) do
for _, curve in pairs(j) do
curve:clear()
end
end
end
end
function setColor(r,g,b,a)
if constants.colors then
love.graphics.setColor(r,g,b,a)
else
love.graphics.setColor(1, 1, 1, a)
end
end
function drawMarker(x, y)
if constants.drawMarkers then
love.graphics.circle("fill", x, y, markerSize)
end
end
function drawCircle(x, y)
if constants.drawCircles then
love.graphics.circle("line", x, y, constants.circleRadius)
end
end
function love.draw()
local w,h = love.graphics.getDimensions()
love.graphics.setLineJoin("none")
love.graphics.setLineStyle("smooth")
-- Circles and lines
for i, circleAngle in pairs(circles) do
local dist = constants.circleRadius + (i+1) * gap*2
local p = i/#circles
-- X-axis
if dist+gap < w then
local x = dist + constants.circleRadius * math.cos(circleAngle-math.pi/2)
local y = gap + constants.circleRadius * math.sin(circleAngle-math.pi/2)
setColor(HSV(p*511, 255, 255))
love.graphics.setLineWidth(constants.circleRadius * relativeWidth)
drawMarker(x, y)
drawCircle(dist, gap)
if constants.drawLines then
setColor(HSV(p*511, 255, 255, opacity))
love.graphics.line(x, 0, x, h)
end
end
-- Y-axis
if dist+gap < h then
local x = gap + constants.circleRadius * math.cos(circleAngle-math.pi/2)
local y = dist + constants.circleRadius * math.sin(circleAngle-math.pi/2)
setColor(HSV(p*511, 255, 255))
love.graphics.setLineWidth(constants.circleRadius * relativeWidth)
drawMarker(x, y)
drawCircle(gap, dist)
if constants.drawLines then
setColor(HSV(p*511, 255, 255, opacity))
love.graphics.line(0, y, w, y)
end
end
end
-- Draw intersection point
for i, circleAngle1 in pairs(circles) do
for j, circleAngle2 in pairs(circles) do
local distX = (constants.circleRadius + (i+1) * gap*2)
local distY = (constants.circleRadius + (j+1) * gap*2)
if distX+gap < w and distY+gap < h then
local x = constants.circleRadius * math.cos(circleAngle1-math.pi/2) + distX
local y = constants.circleRadius * math.sin(circleAngle2-math.pi/2) + distY
setColor(addColors(i/#circles*511, j/#circles*511))
drawMarker(x, y)
curves[i][j]:addPoint(x, y)
end
end
end
-- Draw curves
if constants.drawTable then
for n1, j in pairs(curves) do
for n2, curve in pairs(j) do
setColor(addColors(n1/#circles*511, n2/#circles*511))
curve:draw()
end
end
end
end
function love.resize(w, h)
angle = 0
recalc(w,h)
end