graph drawing tool
intersect_with_centroid = function(node, sx,sy)
	local h = node_height(node)
	local c = centroid(node)
	-- collect nearest intersection with all 4 boundaries
	local candidates = {}
	local y = y_at_x(sx,sy, c.sx,c.sy, node.x-10)
	if y and y >= node.y-10 and y < node.y+h+10 then
		table.insert(candidates, {sx=node.x-10, sy=y})
	end
	y = y_at_x(sx,sy, c.sx,c.sy, node.x+node.w+10)
	if y and y >= node.y-10 and y < node.y+h+10 then
		table.insert(candidates, {sx=node.x+node.w+10, sy=y})
	end
	local x = x_at_y(sx,sy, c.sx,c.sy, node.y-10)
	if x and x >= node.x-10 and x < node.x+node.w+10 then
		table.insert(candidates, {sx=x, sy=node.y-10})
	end
	x = x_at_y(sx,sy, c.sx,c.sy, node.y+h+10)
	if x and x >= node.x-10 and x < node.x+node.w+10 then
		table.insert(candidates, {sx=x, sy=node.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
	table.sort(candidates,
		function(a, b)
			return distance_sq(sx,sy, a.sx,a.sy) < distance_sq(sx,sy, b.sx,b.sy)
		end)
	return candidates[1]
end