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 if math.abs(x1-x2) < 0.0001 then x1 = x1 - 0.01 x2 = x2 + 0.01 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 --]]