From 3b804d82ce5b1896503817ab0707dd019772d116 Mon Sep 17 00:00:00 2001 From: Ze-Zheng Wu Date: Mon, 21 Mar 2022 17:37:18 +0800 Subject: [PATCH] fix center calculation of Bezier edges --- src/components/Edges/BezierEdge.tsx | 46 ++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/components/Edges/BezierEdge.tsx b/src/components/Edges/BezierEdge.tsx index 2608bef7..ce6ae619 100644 --- a/src/components/Edges/BezierEdge.tsx +++ b/src/components/Edges/BezierEdge.tsx @@ -1,7 +1,6 @@ import React, { memo } from 'react'; import { EdgeProps, Position } from '../../types'; import BaseEdge from './BaseEdge'; -import { getCenter } from './utils'; export interface GetBezierPathParams { sourceX: number; @@ -91,6 +90,44 @@ export function getBezierPath({ return `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`; } +// @TODO: this function will recalculate the control points +// one option is to let getXXXPath() return center points +// but will introduce breaking changes +// the getCenter() of other types of edges might need to change, too +export function getBezierCenter({ + sourceX, + sourceY, + sourcePosition = Position.Bottom, + targetX, + targetY, + targetPosition = Position.Top, + curvature = 0.25, +}: GetBezierPathParams): [number, number, number, number] { + const [sourceControlX, sourceControlY] = getControlWithCurvature({ + pos: sourcePosition, + x1: sourceX, + y1: sourceY, + x2: targetX, + y2: targetY, + c: curvature, + }); + const [targetControlX, targetControlY] = getControlWithCurvature({ + pos: targetPosition, + x1: targetX, + y1: targetY, + x2: sourceX, + y2: sourceY, + c: curvature, + }); + // quadratic bezier t=0.5 mid point, not the actual mid point, but easy to calculate + // https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve + const centerX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125; + const centerY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125; + const xOffset = Math.abs(centerX - sourceX); + const yOffset = Math.abs(centerY - sourceY); + return [centerX, centerY, xOffset, yOffset]; +} + export default memo( ({ sourceX, @@ -110,8 +147,7 @@ export default memo( markerStart, curvature, }: EdgeProps) => { - const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }); - const path = getBezierPath({ + const params = { sourceX, sourceY, sourcePosition, @@ -119,7 +155,9 @@ export default memo( targetY, targetPosition, curvature, - }); + }; + const path = getBezierPath(params); + const [centerX, centerY] = getBezierCenter(params); return (