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.
KDIC32VKQ4Z7UAWIJBTUNXZWKJIZ4FTGUN5TCILOLIC5LYWQZEOQC B3ZC44KYSYCCNVPNA7UZL6XFCD27O37PNHZ2SS45Q6V6UXHDW5IAC H3HB2MENN6YV4Y7MGS4FMHKUS4AOV2JHRJRSG27PDTMYHSD2GEAAC R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC FHLFZZ3SG5VGJX25JID6A6C5XLT6Q76RAJDQSYQSZTXQMSIUTCCAC FBDRJ53NJ5BWDQGU2GWZ6NEYHKCCRD7RODMIG7QQZBRFUB4HR7OAC 7UWLGLA6FAO42YN6IBEFAKMTDUY26IJAQDBHGHHH55OK2SHUIZHAC KI6LF2LF2LK6Q7SRWN3U4TJ25Y6BGJ2M3AU5FUTN6JIVA2MUBEXAC M2JTUQQL2JBWHMN3JG6KO6NDHZ5X7ZW2RF7HVG4WVMS5TE6DYUPQC JIBCE66ZTWM5WEHEHNKKTRWBJQSQWBDDWPMOJIJR5Q676OSHYCNAC TBPJ5WSRM5IKQH7FTAVYTWWUBWW7G2CLT5M6FN7CMPLD6Y77YIWQC VEVJJKOCDIODY35MQDZFZU7R77IIGIL7HWMEPZ6J5F2BJFGCP4RQC ZQMQVMFWZIGWBRCB455IKHPTAOUYPLYCSC44NBPPET557RGVRX3AC 3GK7GC2WTTU4K76MD7DN6W4UPSFTYSEJMTGG4P7ADEHLH6K3P4IQC 7OUKVXJTWEJBYNBPB2SBXJ4ADFZ7OV4SJEG4K2A3J4D7FSJAJ52QC distance_sq = function(x1,y1, x2,y2)return (x2-x1)^2+(y2-y1)^2end
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 thenreturnendreturn (endx-startx)/(endy-starty)*(y-starty) + startxend
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 thenreturnendreturn (endy-starty)/(endx-startx)*(x-startx) + startyend
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 thenif sy > c.sy thenreturn {sx=sx, sy=Edge.source.y + h + 10}elsereturn {sx=sx, sy=Edge.source.y - 10}endend-- collect nearest intersection with all 4 boundarieslocal 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 thentable.insert(candidates, {sx=Edge.source.x-10, sy=y})endy = 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 thentable.insert(candidates, {sx=Edge.source.x+Edge.source.w+10, sy=y})endlocal 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 thentable.insert(candidates, {sx=x, sy=Edge.source.y-10})endx = 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 thentable.insert(candidates, {sx=x, sy=Edge.source.y+h+10})endif #candidates == 0 then-- no intersection; just return the same pointreturn {sx=sx, sy=sy}endif #candidates == 1 thenreturn candidates[1]endassert(#candidates == 2)if distance_sq(sx,sy, candidates[1].sx, candidates[1].sy) < distance_sq(sx,sy, candidates[2].sx, candidates[2].sy) thenreturn candidates[1]elsereturn candidates[2]endend
node_height = function(node)-- we store the node's height internally, but it can be too smallreturn math.max(node.h, 3*node.editor.line_height)end
table.length = function(h)-- length of a table (not just the array side)local result = 0for _ in pairs(h) doresult = result+1endreturn resultend
if Border thenApp.color{r=0,g=1,b=1}love.graphics.circle('fill', vx(Border.sx),vy(Border.sy), 5)
if Edge thenApp.color{r=0,g=0,b=1}if Edge.s.debug_info thenfor _,p in ipairs(Edge.s.debug_info) dolove.graphics.circle('line', vx(p.sx), vy(p.sy), 5)endendApp.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)
elseif Border thenBorder = nil
elseif Edge thenlocal src = Edge.sourcelocal line_height = Edge.source.editor.line_heightlocal 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] = desttable.insert(Nodes[src.id].outgoing_edges, dest.id)Edge = nilA()