keep edges short

This had some dead ends. I spent some time trying to use the
parametric equation of a line. But the parameter is not comparable
across two lines.
This commit is contained in:
Kartik K. Agaram 2023-04-18 22:16:49 -07:00
parent 880ecc0efd
commit 770ab80074
15 changed files with 109 additions and 18 deletions

View File

@ -24,9 +24,9 @@ on.mouse_press = function(x,y, mouse_button)
end
node = on_border(sx,sy)
if node then
Border = {sx=sx, sy=sy}
Edge = {source=node, s={sx=sx, sy=sy}, e={sx=sx, sy=sy}}
return
end
-- default
Pan = {sx=sx,sy=sy}
end
end

View File

@ -1,8 +1,14 @@
on.mouse_release = function(x,y, mouse_button)
if Pan then
Pan = nil
elseif Border then
Border = nil
elseif Edge then
local src = Edge.source
local line_height = Edge.source.editor.line_height
local dest = {id=next_key(), type='text', x=sx(x)-60,y=sy(y)-1.5*line_height, margin=0, width=120, outgoing_edges={}, incoming_edges={src.id}}
Nodes[dest.id] = dest
table.insert(Nodes[src.id].outgoing_edges, dest.id)
Edge = nil
A()
elseif Resize_node then
Resize_node = nil
Resize = nil

View File

@ -7,7 +7,10 @@ on.update = function(dt)
end
local sx = sx(App.mouse_x())
local sy = sy(App.mouse_y())
if Move_node then
if Edge then
Edge.s = intersect_with_centroid(Edge.source, sx,sy)
Edge.e = {sx=sx, sy=sy}
elseif Move_node then
Move_node.x = sx - Move.sx
Move_node.y = sy - Move.sy
A1(Move_node.id)

View File

@ -31,7 +31,7 @@ compute_layout = function(node, x,y, nodes_to_render, preserve_screen_top_of_cur
table.insert(nodes_to_render, node)
move_bar.w = node.w/2
bounding_box.w = node.w+20
local buffer_height = math.max(node.h, 3*node.editor.line_height)
local buffer_height = node_height(node)
bounding_box.h = buffer_height+20
-- resize affordance
table.insert(nodes_to_render, {type='line', r=0.7,g=0.7,b=0.7, data={node.x+node.w+20,node.y, node.x+node.w+20,node.y+buffer_height}, id=node.id})

View File

@ -22,8 +22,16 @@ on.draw = function()
end
end
end
if Border then
App.color{r=0,g=1,b=1}
love.graphics.circle('fill', vx(Border.sx),vy(Border.sy), 5)
if Edge then
App.color{r=0,g=0,b=1}
if Edge.s.debug_info then
for _,p in ipairs(Edge.s.debug_info) do
love.graphics.circle('line', vx(p.sx), vy(p.sy), 5)
end
end
App.color{r=0,g=0,b=0}
love.graphics.line(vx(Edge.s.sx),vy(Edge.s.sy), vx(Edge.e.sx),vy(Edge.e.sy))
love.graphics.circle('fill', vx(Edge.s.sx),vy(Edge.s.sy), 5)
love.graphics.circle('fill', vx(Edge.e.sx),vy(Edge.e.sy), 5)
end
end

View File

@ -1,3 +1,3 @@
Nodes = {
a={type='text', x=0,y=0, margin=0, width=120},
a={type='text', x=0,y=0, margin=0, width=120, outgoing_edges={}, incoming_edges={}},
}

View File

@ -1,10 +1,9 @@
on_resize = function(sx,sy)
for _,node in pairs(Nodes) do
if sx >= node.x+node.w+20 and sx < node.x+node.w+24 then
local buffer_height = math.max(node.h, 3*node.editor.line_height)
if sy >= node.y and sy < node.y+buffer_height then
if sy >= node.y and sy < node.y+node_height(node) then
return node
end
end
end
end
end

View File

@ -2,8 +2,7 @@ on_node = function(sx,sy)
for _,node in ipairs(Surface) do
if node.type == 'text' then
if sx >= node.x and sx < node.x + node.w then
local buffer_height = math.max(node.h, 3*node.editor.line_height)
if sy >= node.y and sy < node.y + buffer_height then
if sy >= node.y and sy < node.y + node_height(node) then
return node
end
end

View File

@ -5,15 +5,15 @@ on_border = function(sx,sy)
end
for _,node in ipairs(Surface) do
if node.type == 'text' then
local h = math.max(node.h, 3*node.editor.line_height)
local h = node_height(node)
if sx >= node.x-10-corner_radius and sx < node.x + node.w+10+corner_radius then
if near(sy, node.y-10) or near(sy, node.y+h+10) then
return true
return node
end
end
if sy >= node.y-10-corner_radius and sy < node.y + h+10+corner_radius then
if near(sx, node.x-10) or near(sx, node.x+node.w+10) then
return true
return node
end
end
end

8
0049-table.length Normal file
View File

@ -0,0 +1,8 @@
table.length = function(h)
-- length of a table (not just the array side)
local result = 0
for _ in pairs(h) do
result = result+1
end
return result
end

4
0050-node_height Normal file
View File

@ -0,0 +1,4 @@
node_height = function(node)
-- we store the node's height internally, but it can be too small
return math.max(node.h, 3*node.editor.line_height)
end

View File

@ -0,0 +1,45 @@
intersect_with_centroid = function(node, sx,sy)
local h = node_height(Edge.source)
local c = {
sx=Edge.source.x + Edge.source.w/2,
sy=Edge.source.y + h/2
}
if c.sx == sx then
if sy > c.sy then
return {sx=sx, sy=Edge.source.y + h + 10}
else
return {sx=sx, sy=Edge.source.y - 10}
end
end
-- collect nearest intersection with all 4 boundaries
local candidates = {}
local y = y_at_x(sx,sy, c.sx,c.sy, Edge.source.x-10)
if y and y >= Edge.source.y-10 and y < Edge.source.x+h+10 then
table.insert(candidates, {sx=Edge.source.x-10, sy=y})
end
y = y_at_x(sx,sy, c.sx,c.sy, Edge.source.x + Edge.source.w + 10)
if y and y >= Edge.source.y-10 and y < Edge.source.x+h+10 then
table.insert(candidates, {sx=Edge.source.x+Edge.source.w+10, sy=y})
end
local x = x_at_y(sx,sy, c.sx,c.sy, Edge.source.y-10)
if x and x >= Edge.source.x-10 and x < Edge.source.x + Edge.source.w + 10 then
table.insert(candidates, {sx=x, sy=Edge.source.y-10})
end
x = x_at_y(sx,sy, c.sx,c.sy, Edge.source.y+h+10)
if x and x >= Edge.source.x-10 and x < Edge.source.x + Edge.source.w + 10 then
table.insert(candidates, {sx=x, sy=Edge.source.y+h+10})
end
if #candidates == 0 then
-- no intersection; just return the same point
return {sx=sx, sy=sy}
end
if #candidates == 1 then
return candidates[1]
end
assert(#candidates == 2)
if distance_sq(sx,sy, candidates[1].sx, candidates[1].sy) < distance_sq(sx,sy, candidates[2].sx, candidates[2].sy) then
return candidates[1]
else
return candidates[2]
end
end

8
0055-y_at_x Normal file
View File

@ -0,0 +1,8 @@
y_at_x = function(startx,starty, endx,endy, x)
-- y at a given x on a line
-- Could be nil when the line is parallel to the y axis.
if startx == endx then
return
end
return (endy-starty)/(endx-startx)*(x-startx) + starty
end

8
0056-x_at_y Normal file
View File

@ -0,0 +1,8 @@
x_at_y = function(startx,starty, endx,endy, y)
-- x at a given y on a line
-- Could be nil when the line is parallel to the x axis.
if starty == endy then
return
end
return (endx-startx)/(endy-starty)*(y-starty) + startx
end

3
0057-distance_sq Normal file
View File

@ -0,0 +1,3 @@
distance_sq = function(x1,y1, x2,y2)
return (x2-x1)^2+(y2-y1)^2
end