local catmull = require'path2d_catmullrom' local bezier3 = require'path2d_bezier3' local player = require'cplayer' local function eq(a, b) return math.abs(a - b) < 1e-12 end --generate random catmull-friendly points math.randomseed(os.time()) local t = {} local x, y = 50,200 for i=1,24 do table.insert(t, {x, y}) x = x + math.random(10, 100) y = y + math.random(-100, 100) end table.insert(t, {200, 100}) --close the curve t[#t-1] = t[2] t[#t] = t[3] t[1] = t[#t-2] local k = 1 function player:on_render(cr) k = self:slider{id = 'k', x = 10, y = 10, w = 100, h = 26, i0 = -2, i1 = 2, step = 0.01, i = k} for i=1,#t do t[i][1], t[i][2] = self:dragpoint{id = 'p'..i, x = t[i][1], y = t[i][2]} end for i=1,#t-3 do local x1, y1, x2, y2, x3, y3, x4, y4 = t[i][1], t[i][2], t[i+1][1], t[i+1][2], t[i+2][1], t[i+2][2], t[i+3][1], t[i+3][2] --conversion to bezier and back: test precision local ak, ax1, ay1, ax2, ay2, ax3, ay3, ax4, ay4 = bezier3.to_catmullrom(catmull.to_bezier3(1, x1, y1, x2, y2, x3, y3, x4, y4)) assert(eq(ax1, x1)) assert(eq(ay1, y1)) assert(eq(ax2, x2)) assert(eq(ay2, y2)) assert(eq(ax3, x3)) assert(eq(ay3, y3)) assert(eq(ax4, x4)) assert(eq(ay4, y4)) --linear interpolation for t=0,1,0.1 do local x, y = catmull.point(t, k, x1, y1, x2, y2, x3, y3, x4, y4) self:dot(x, y, 2) end --bezier conversion x1, y1, x2, y2, x3, y3, x4, y4 = catmull.to_bezier3(k, x1, y1, x2, y2, x3, y3, x4, y4) self:dot(x1, y1, 2) self:dot(x2, y2, 2) self:dot(x3, y3, 2) self:dot(x4, y4, 2) self:curve(x1, y1, x2, y2, x3, y3, x4, y4) end end player:play()