fix center calculation of Bezier edges

This commit is contained in:
Ze-Zheng Wu
2022-03-21 17:37:18 +08:00
parent 0ee882d2c1
commit 3b804d82ce
+42 -4
View File
@@ -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 (
<BaseEdge