bezier-string-art/BezierCurve.lua
2023-05-11 21:28:37 +03:00

99 lines
2.5 KiB
Lua

local Vector2 = require("Vector2")
local BezierCurve = {}
local width = 5
local interval = 1/10
BezierCurve.maxDepth = -1
BezierCurve.randSeed = love.math.random()
BezierCurve.__index = BezierCurve
local function dist(x1,y1,x2,y2)
return ((x1-x2)^2+(y1-y2)^2)^0.5
end
local function linearBezier(p1, p2)
return (1-t)*p1 + t*p2
end
function BezierCurve.new(class, points)
return setmetatable({
_curve = love.math.newBezierCurve(points or {100,180,250,250,200,500}),
selectedPoint = false
}, class)
end
function BezierCurve:draw(drawPoints, drawLines, drawFinal)
love.graphics.setLineJoin("bevel")
love.graphics.setLineStyle("smooth")
if drawLines then
love.graphics.setLineWidth(width*0.25)
local p = {}
for i=1, self._curve:getControlPointCount() do
table.insert(p, Vector2(self._curve:getControlPoint(i)))
end
BezierCurve.stringArt(p, 0)
end
if drawFinal then
love.graphics.setLineWidth(width)
love.graphics.setColor(0.8,0,0)
love.graphics.line(self._curve:render())
end
if drawPoints then
love.graphics.setColor(0,0,0.8)
for i=1,self._curve:getControlPointCount() do
local x,y = self._curve:getControlPoint(i)
love.graphics.circle("fill",x,y,width*1.25)
end
end
end
function BezierCurve:mousemoved(x, y)
if self.selectedPoint then
self._curve:setControlPoint(self.selectedPoint, x, y)
end
end
function BezierCurve:mousepressed(x, y, button)
if button == 1 then
local isCtrl = love.keyboard.isDown("lctrl", "rctrl")
for i=1,self._curve:getControlPointCount() do
if dist(x,y,self._curve:getControlPoint(i)) < width*1.25 then
if isCtrl then
self._curve:removeControlPoint(i)
else
self.selectedPoint = i
end
return
end
end
if isCtrl then
self._curve:insertControlPoint(x, y)
end
end
end
function BezierCurve:mousereleased(_, _, button)
if button == 1 then
self.selectedPoint = false
end
end
function BezierCurve.stringArt(points, depth)
if #points > 2 and (BezierCurve.maxDepth < 0 or depth < BezierCurve.maxDepth) then
for t=0,1,interval do
love.graphics.setColor(0.3,0.5,0.1)
local p = {}
for pointI=1, #points-1 do
table.insert(p, (1-t)*points[pointI] + t*points[pointI+1])
end
for pointI=1, #p-1 do
love.graphics.line(p[pointI].x, p[pointI].y, p[pointI+1].x, p[pointI+1].y)
end
BezierCurve.stringArt(p, depth+1)
end
end
end
return BezierCurve