fix center calculation of simple Bezier edges
This commit is contained in:
@@ -10,8 +10,6 @@ export interface GetBezierPathParams {
|
|||||||
targetY: number;
|
targetY: number;
|
||||||
targetPosition?: Position;
|
targetPosition?: Position;
|
||||||
curvature?: number;
|
curvature?: number;
|
||||||
centerX?: number;
|
|
||||||
centerY?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetControlWithCurvatureParams {
|
interface GetControlWithCurvatureParams {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import { EdgeProps, Position } from '../../types';
|
import { EdgeProps, Position } from '../../types';
|
||||||
import BaseEdge from './BaseEdge';
|
import BaseEdge from './BaseEdge';
|
||||||
import { getCenter } from './utils';
|
|
||||||
|
|
||||||
export interface GetSimpleBezierPathParams {
|
export interface GetSimpleBezierPathParams {
|
||||||
sourceX: number;
|
sourceX: number;
|
||||||
@@ -10,33 +9,31 @@ export interface GetSimpleBezierPathParams {
|
|||||||
targetX: number;
|
targetX: number;
|
||||||
targetY: number;
|
targetY: number;
|
||||||
targetPosition?: Position;
|
targetPosition?: Position;
|
||||||
centerX?: number;
|
|
||||||
centerY?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetControlParams {
|
interface GetControlParams {
|
||||||
pos: Position;
|
pos: Position;
|
||||||
x: number;
|
x1: number;
|
||||||
y: number;
|
y1: number;
|
||||||
cX: number;
|
x2: number;
|
||||||
cY: number;
|
y2: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getControl({ pos, x, y, cX, cY }: GetControlParams): [number, number] {
|
function getControl({ pos, x1, y1, x2, y2 }: GetControlParams): [number, number] {
|
||||||
let ctX: number, ctY: number;
|
let ctX: number, ctY: number;
|
||||||
switch (pos) {
|
switch (pos) {
|
||||||
case Position.Left:
|
case Position.Left:
|
||||||
case Position.Right:
|
case Position.Right:
|
||||||
{
|
{
|
||||||
ctX = cX;
|
ctX = 0.5 * (x1 + x2);
|
||||||
ctY = y;
|
ctY = y1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Position.Top:
|
case Position.Top:
|
||||||
case Position.Bottom:
|
case Position.Bottom:
|
||||||
{
|
{
|
||||||
ctX = x;
|
ctX = x1;
|
||||||
ctY = cY;
|
ctY = 0.5 * (y1 + y2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -50,29 +47,59 @@ export function getSimpleBezierPath({
|
|||||||
targetX,
|
targetX,
|
||||||
targetY,
|
targetY,
|
||||||
targetPosition = Position.Top,
|
targetPosition = Position.Top,
|
||||||
centerX,
|
|
||||||
centerY,
|
|
||||||
}: GetSimpleBezierPathParams): string {
|
}: GetSimpleBezierPathParams): string {
|
||||||
const [_centerX, _centerY] = getCenter({ sourceX, sourceY, targetX, targetY });
|
|
||||||
centerX = centerX ?? _centerX;
|
|
||||||
centerY = centerY ?? _centerY;
|
|
||||||
const [sourceControlX, sourceControlY] = getControl({
|
const [sourceControlX, sourceControlY] = getControl({
|
||||||
pos: sourcePosition,
|
pos: sourcePosition,
|
||||||
x: sourceX,
|
x1: sourceX,
|
||||||
y: sourceY,
|
y1: sourceY,
|
||||||
cX: centerX,
|
x2: targetX,
|
||||||
cY: centerY,
|
y2: targetY,
|
||||||
});
|
});
|
||||||
const [targetControlX, targetControlY] = getControl({
|
const [targetControlX, targetControlY] = getControl({
|
||||||
pos: targetPosition,
|
pos: targetPosition,
|
||||||
x: targetX,
|
x1: targetX,
|
||||||
y: targetY,
|
y1: targetY,
|
||||||
cX: centerX,
|
x2: sourceX,
|
||||||
cY: centerY,
|
y2: sourceY,
|
||||||
});
|
});
|
||||||
return `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`;
|
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 getSimpleBezierCenter({
|
||||||
|
sourceX,
|
||||||
|
sourceY,
|
||||||
|
sourcePosition = Position.Bottom,
|
||||||
|
targetX,
|
||||||
|
targetY,
|
||||||
|
targetPosition = Position.Top,
|
||||||
|
}: GetSimpleBezierPathParams): [number, number, number, number] {
|
||||||
|
const [sourceControlX, sourceControlY] = getControl({
|
||||||
|
pos: sourcePosition,
|
||||||
|
x1: sourceX,
|
||||||
|
y1: sourceY,
|
||||||
|
x2: targetX,
|
||||||
|
y2: targetY,
|
||||||
|
});
|
||||||
|
const [targetControlX, targetControlY] = getControl({
|
||||||
|
pos: targetPosition,
|
||||||
|
x1: targetX,
|
||||||
|
y1: targetY,
|
||||||
|
x2: sourceX,
|
||||||
|
y2: sourceY,
|
||||||
|
});
|
||||||
|
// 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(
|
export default memo(
|
||||||
({
|
({
|
||||||
sourceX,
|
sourceX,
|
||||||
@@ -91,15 +118,16 @@ export default memo(
|
|||||||
markerEnd,
|
markerEnd,
|
||||||
markerStart,
|
markerStart,
|
||||||
}: EdgeProps) => {
|
}: EdgeProps) => {
|
||||||
const [centerX, centerY] = getCenter({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition });
|
const params = {
|
||||||
const path = getSimpleBezierPath({
|
|
||||||
sourceX,
|
sourceX,
|
||||||
sourceY,
|
sourceY,
|
||||||
sourcePosition,
|
sourcePosition,
|
||||||
targetX,
|
targetX,
|
||||||
targetY,
|
targetY,
|
||||||
targetPosition,
|
targetPosition,
|
||||||
});
|
};
|
||||||
|
const path = getSimpleBezierPath(params);
|
||||||
|
const [centerX, centerY] = getSimpleBezierCenter(params);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseEdge
|
<BaseEdge
|
||||||
|
|||||||
Reference in New Issue
Block a user