diff options
Diffstat (limited to 'catenary.lua')
-rw-r--r-- | catenary.lua | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/catenary.lua b/catenary.lua new file mode 100644 index 0000000..abe18e1 --- /dev/null +++ b/catenary.lua @@ -0,0 +1,133 @@ +local G = love.graphics + +local function atanh(x) + return (1/2) * math.log((1+x)/(1-x)) +end + +local function solve_for_A(r) + local A + if r < 3 then + A = math.sqrt(6 * (r-1)) + else + A = math.log(2*r) + math.log(math.log(2*r)) + end + for i=1,5 do + A = A - (math.sinh(A) - r*A)/(math.cosh(A)-r) + end + return A +end + +local function plot(f,x0,xn) + local n = 30 + x0 = x0 or G.inverseTransformPoint(0,0) + xn = xn or G.inverseTransformPoint(G.getDimensions(),0) + + if xn < x0 then + xn,x0 = x0,xn + end + + local h = (xn-x0)/n + local ps = {} + for i=0,n do + local x = x0 + i*h + local y = f(x) + table.insert(ps,x) + table.insert(ps,y) + end + return ps +end + +local function catenary0(x1,y1,x2,y2, L) + -- https://math.stackexchange.com/a/3557768 + y1 = -y1 + y2 = -y2 + local dx = x2-x1 + local dy = y2-y1 + local mx = (x1+x2)/2 + local my = (y1+y2)/2 + + local D = math.sqrt(dx^2+dy^2) + L = L or D+(1/(D+0.3)) + + local r = math.sqrt(L^2 - dy^2)/dx + local A = solve_for_A(r) + + local a = dx/(2*A) + local b = mx - a*atanh(dy/L) + local c = my - L/(2*math.tanh(A)) + + return function(x) return -(a * math.cosh((x-b)/a) + c) end +end + + +local function catenary(x1,y1, x2,y2, L) + local D = math.sqrt((x2-x1)^2 + (y2-y1)^2) + -- L = L or D+(1/(D+0.3)) + L = L or D+(0.1/(D+0.1)) + -- L = D + 0.1 + + if x2 < x1 then + x1,x2 = x2,x1 + y1,y2 = y2,y1 + end + + local f = catenary0(x1,y1,x2,y2,L) + return plot(f, x1,x2) +end + +return { + catenary = catenary +} + + +--[[ +local Ps = {{-1,1}, {1,1}} + +function love.update(dt) + for b = 1,2 do + if love.mouse.isDown(b) then + Ps[b] = {G.inverseTransformPoint(love.mouse.getPosition())} + end + end +end + + +function love.draw() + local W,H = G.getDimensions() + G.clear(1,1,1) + G.setColor(0,0,0) + G.origin() + local dx = Ps[1][1] - Ps[2][1] + local dy = Ps[1][2] - Ps[2][2] + local D = math.sqrt(dx^2+dy^2) + local L = D+(1/(D+0.3)) + -- local L = D+1 + G.print(("%.2f\n%.2f\n%.2f"):format(L,D,L-D),10,10) + G.setLineWidth(0.01) + G.translate(W/2,H/2) + G.scale(50) + + G.setColor(0.8,0.8,0.8) + for i=-10,10 do + G.line(-10,i,10,i) + G.line(i,-10,i,10) + end + + G.circle('line',0,0,1) + + -- G.setColor(0,0,0) + -- -- plot(function(x) return x^2 end) + -- plot(math.tanh) + -- G.setColor(0,1,0) + -- plot(atanh) + + G.setColor(0,0,0) + G.line(catenary(Ps[1][1],Ps[1][2], Ps[2][1], Ps[2][2])) + + G.setColor(1,0,0) + G.circle('fill',Ps[1][1],Ps[1][2],0.05) + G.setColor(0,0,1) + G.circle('fill',Ps[2][1],Ps[2][2],0.05) +end +--]] + |