1
0

feat: Initial commit

This commit is contained in:
Rokas Puzonas 2021-06-01 19:08:10 +03:00
commit db930b13fb
4 changed files with 232 additions and 0 deletions

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# Lissajous table
![Preview](example.gif)
I was inspired by this video "[Making a physical Lissajous curve](https://www.youtube.com/watch?v=4CbPksEl51Q)"
and thought "That looks pretty cool and easy to code". So here it is a program
which draws a resizable lissajous table. The wider or higher your window is
the more circles will be drawn.
## Starting
To run this project you need to install [Love2D](https://love2d.org) yourself.
There is a great tutorial on how to do all of this [here](https://love2d.org/wiki/Getting_Started).

4
conf.lua Normal file
View File

@ -0,0 +1,4 @@
function love.conf(t)
t.window.title = "Lissajous tables"
t.window.resizable = true
end

BIN
example.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

214
main.lua Normal file
View File

@ -0,0 +1,214 @@
-- 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