import type { GraphNode, XYPosition } from '@vue-flow/core' import { Position } from '@vue-flow/core' // this helper function returns the intersection point // of the line between the center of the intersectionNode and the target node function getNodeIntersection(intersectionNode: GraphNode, targetNode: GraphNode) { // https://math.stackexchange.com/questions/1724792/an-algorithm-for-finding-the-intersection-point-between-a-center-of-vision-and-a const { dimensions: { width: intersectionNodeWidth, height: intersectionNodeHeight }, computedPosition: intersectionNodePosition, } = intersectionNode const targetPosition = targetNode.computedPosition const w = intersectionNodeWidth / 2 const h = intersectionNodeHeight / 2 const x2 = intersectionNodePosition.x + w const y2 = intersectionNodePosition.y + h const x1 = targetPosition.x + w const y1 = targetPosition.y + h const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h) const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h) const a = 1 / (Math.abs(xx1) + Math.abs(yy1)) const xx3 = a * xx1 const yy3 = a * yy1 const x = w * (xx3 + yy3) + x2 const y = h * (-xx3 + yy3) + y2 return { x, y } } // returns the position (top,right,bottom or right) passed node compared to the intersection point function getEdgePosition(node: GraphNode, intersectionPoint: XYPosition) { const n = { ...node.computedPosition, ...node } const nx = Math.round(n.x) const ny = Math.round(n.y) const px = Math.round(intersectionPoint.x) const py = Math.round(intersectionPoint.y) if (px <= nx + 1) { return Position.Left } if (px >= nx + n.dimensions.width - 1) { return Position.Right } if (py <= ny + 1) { return Position.Top } if (py >= n.y + n.dimensions.height - 1) { return Position.Bottom } return Position.Top } // returns the parameters (sx, sy, tx, ty, sourcePos, targetPos) you need to create an edge export function getEdgeParams(source: GraphNode, target: GraphNode) { const sourceIntersectionPoint = getNodeIntersection(source, target) const targetIntersectionPoint = getNodeIntersection(target, source) const sourcePos = getEdgePosition(source, sourceIntersectionPoint) const targetPos = getEdgePosition(target, targetIntersectionPoint) return { sx: sourceIntersectionPoint.x, sy: sourceIntersectionPoint.y, tx: targetIntersectionPoint.x, ty: targetIntersectionPoint.y, sourcePos, targetPos, } }