summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-01-04 22:47:17 +0000
committerubq323 <ubq323@ubq323.website>2024-01-04 22:47:17 +0000
commitfb3c96b1783e575165417d01858fbd100696a283 (patch)
treefe1a5e30b95e8b8a5fc819fbb19151c2608bedf4
parent9f31c5506d7c7cb8194a712fcd2d90695b69f370 (diff)
joining
-rw-r--r--catenary.lua133
-rw-r--r--main.lua190
-rw-r--r--main_old.lua86
3 files changed, 224 insertions, 185 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
+--]]
+
diff --git a/main.lua b/main.lua
index 7b0a7c0..d1a84a8 100644
--- a/main.lua
+++ b/main.lua
@@ -1,131 +1,123 @@
+local class = require 'class'
+local hsluv = require 'hsluv'
+local catenary = require 'catenary'
+
+local tau = 2*math.pi
+local ZOOM = 200
local G = love.graphics
-local function atanh(x)
- return (1/2) * math.log((1+x)/(1-x))
+local function write_at(text,x,y)
+ G.push()
+ G.translate(x,y)
+ G.scale(1/ZOOM)
+ G.print(text,0,0)
+ G.pop()
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
+local Port = class()
+Port.R = 0.1
+function Port.make(cls, x,y, num)
+ return setmetatable({x=x,y=y,n=num,wires={}},cls)
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)
+function Port.draw(self, istate)
+ local c = {0,0,0}
+ if istate == 'hover' then
+ c[1] = 1
+ elseif istate == 'selected' then
+ c[2] = 1
end
- return ps
+ love.graphics.setColor(c)
+ G.circle('line',self.x,self.y,self.R)
+ write_at(self.n, self.x, self.y)
+end
+function Port.contains(self, px,py)
+ local d = math.sqrt((self.x - px)^2 + (self.y - py)^2)
+ return d <= self.R
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 ports = {}
+local n = 10
+for i = 1,n do
+ local theta = tau * i/n
+ table.insert(ports, Port:make(math.cos(theta), math.sin(theta), i))
+end
+ports[3].wires = {ports[6]}
+ports[5].wires = {ports[7],ports[2]}
- 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
+local function wire_color(n)
+ local phi = (1+math.sqrt(5))/2
+ local h = (360*phi*n)%360
+ return hsluv.hsluv_to_rgb({h, 80, 60})
end
+local state = 'normal'
+local selected = nil
-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))
-
- if x2 < x1 then
- x1,x2 = x2,x1
- y1,y2 = y2,y1
+local function hovering_port(mx,my)
+ for i,p in ipairs(ports) do
+ if p:contains(mx,my) then
+ return p
+ end
end
-
- local f = catenary0(x1,y1,x2,y2,L)
- return plot(f, x1,x2)
+ return nil
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())}
+function love.mousepressed(x,y,b)
+ if b == 2 then
+ state = 'normal'
+ selected = nil
+ return
+ end
+ local mx,my = G.inverseTransformPoint(x,y)
+ local p = hovering_port(mx,my)
+ if p then
+ if state == 'normal' then
+ state = 'joining'
+ selected = p.n
+ elseif state == 'joining' then
+ table.insert(ports[selected].wires, p)
+ state = 'normal'
+ selected = nil
end
end
end
+
+local L = 2
+function love.wheelmoved(x,y)
+ L = L + (y/15)
+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.print(L,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)
+ G.scale(ZOOM)
+
+ local mx,my = G.inverseTransformPoint(love.mouse.getPosition())
+ local wn = 0
+ for i,p in ipairs(ports) do
+ local istate = 'normal'
+ if p:contains(mx,my) then istate = 'hover' end
+ if state ~= 'normal' and selected == i then istate = 'selected' end
+ p:draw(istate)
+ for _,q in ipairs(p.wires) do
+ G.setColor(wire_color(wn))
+ wn = wn + 1
+ G.line(catenary.catenary(p.x,p.y,q.x,q.y))
+ end
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)
+ if state == 'joining' then
+ G.setColor(wire_color(wn))
+ local p = ports[selected]
+ G.line(catenary.catenary(p.x,p.y,mx,my))
+ end
end
---]]
diff --git a/main_old.lua b/main_old.lua
deleted file mode 100644
index 160a0d7..0000000
--- a/main_old.lua
+++ /dev/null
@@ -1,86 +0,0 @@
-local class = require 'class'
-local hsluv = require 'hsluv'
-
-local tau = 2*math.pi
-local ZOOM = 200
-local G = love.graphics
-
-local function write_at(text,x,y)
- G.push()
- G.translate(x,y)
- G.scale(1/ZOOM)
- G.print(text,0,0)
- G.pop()
-end
-
-local Port = class()
-Port.R = 0.1
-function Port.make(cls, x,y, num)
- return setmetatable({x=x,y=y,n=num,wires={}},cls)
-end
-function Port.draw(self, istate)
- local c = {0,0,0}
- if istate == 'hover' then
- c[1] = 1
- end
- love.graphics.setColor(c)
- G.circle('line',self.x,self.y,self.R)
- write_at(self.n, self.x, self.y)
-end
-function Port.contains(self, px,py)
- local d = math.sqrt((self.x - px)^2 + (self.y - py)^2)
- return d <= self.R
-end
-
-local ports = {}
-local n = 10
-for i = 1,n do
- local theta = tau * i/n
- table.insert(ports, Port:make(math.cos(theta), math.sin(theta), i))
-end
-ports[3].wires = {ports[6]}
-ports[5].wires = {ports[7],ports[2]}
-for i = 1,15 do
- local r1,r2 = math.random(10), math.random(10)
- if r1 ~= r2 then
- table.insert(ports[r1].wires, ports[r2])
- end
-end
-
-
-local function catenary(x1,y1,x2,y2)
- -- https://math.stackexchange.com/questions/3557767/how-to-construct-a-catenary-of-a-specified-length-through-two-specified-points
-
-end
-
-local function wire_color(n)
- local phi = (1+math.sqrt(5))/2
- local h = (360*phi*n)%360
- return hsluv.hsluv_to_rgb({h, 80, 60})
-end
-
-local state = 'normal'
-
-
-function love.draw()
- local W,H = G.getDimensions()
- G.clear(1,1,1)
- G.setColor(0,0,0)
- G.origin()
- G.setLineWidth(0.01)
- G.translate(W/2,H/2)
- G.scale(ZOOM)
-
- local mx,my = G.inverseTransformPoint(love.mouse.getPosition())
- local wn = 0
- for i,p in ipairs(ports) do
- local istate = p:contains(mx,my) and 'hover' or 'normal'
- p:draw(istate)
- for _,q in ipairs(p.wires) do
- G.setColor(wire_color(wn))
- wn = wn + 1
- catenary(p.x,p.y,q.x,q.y)
- end
- end
-end
-