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:
parent
880ecc0efd
commit
770ab80074
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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})
|
||||
|
|
14
0026-on.draw
14
0026-on.draw
|
@ -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
|
|
@ -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={}},
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
distance_sq = function(x1,y1, x2,y2)
|
||||
return (x2-x1)^2+(y2-y1)^2
|
||||
end
|
Loading…
Reference in New Issue