summaryrefslogtreecommitdiff
path: root/catenary.lua
diff options
context:
space:
mode:
Diffstat (limited to 'catenary.lua')
-rw-r--r--catenary.lua133
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
+--]]
+