Fix fake orthogonal target-entry hook detection

This commit is contained in:
master
2026-03-26 14:39:55 +02:00
parent c210115224
commit 2bc06169f8
3 changed files with 1368 additions and 2 deletions

View File

@@ -9647,6 +9647,11 @@ internal static class ElkEdgePostProcessor
}
const double tolerance = 0.5d;
if (HasShortOrthogonalTargetHook(path, targetNode, side, tolerance))
{
return true;
}
var startIndex = Math.Max(0, path.Count - (side is "left" or "right" ? 4 : 3));
var axisValues = new List<double>(path.Count - startIndex);
for (var i = startIndex; i < path.Count; i++)
@@ -9722,6 +9727,85 @@ internal static class ElkEdgePostProcessor
return false;
}
private static bool HasShortOrthogonalTargetHook(
IReadOnlyList<ElkPoint> path,
ElkPositionedNode targetNode,
string side,
double tolerance)
{
if (path.Count < 3)
{
return false;
}
var boundaryPoint = path[^1];
var runStartIndex = path.Count - 2;
if (side is "left" or "right")
{
while (runStartIndex > 0 && Math.Abs(path[runStartIndex - 1].Y - boundaryPoint.Y) <= tolerance)
{
runStartIndex--;
}
}
else
{
while (runStartIndex > 0 && Math.Abs(path[runStartIndex - 1].X - boundaryPoint.X) <= tolerance)
{
runStartIndex--;
}
}
if (runStartIndex == 0)
{
return false;
}
var overallDeltaX = path[^1].X - path[0].X;
var overallDeltaY = path[^1].Y - path[0].Y;
var overallAbsDx = Math.Abs(overallDeltaX);
var overallAbsDy = Math.Abs(overallDeltaY);
var sameRowThreshold = Math.Max(24d, targetNode.Height / 3d);
var sameColumnThreshold = Math.Max(24d, targetNode.Width / 3d);
var looksHorizontal = overallAbsDx >= overallAbsDy * 1.15d
&& overallAbsDy <= sameRowThreshold
&& Math.Sign(overallDeltaX) != 0;
var looksVertical = overallAbsDy >= overallAbsDx * 1.15d
&& overallAbsDx <= sameColumnThreshold
&& Math.Sign(overallDeltaY) != 0;
var contradictsDominantApproach = side switch
{
"left" or "right" => looksVertical,
"top" or "bottom" => looksHorizontal,
_ => false,
};
if (!contradictsDominantApproach)
{
return false;
}
var runStart = path[runStartIndex];
var boundaryDepth = side is "left" or "right"
? Math.Abs(boundaryPoint.X - runStart.X)
: Math.Abs(boundaryPoint.Y - runStart.Y);
var requiredDepth = side is "left" or "right"
? targetNode.Width
: targetNode.Height;
if (boundaryDepth + tolerance >= requiredDepth)
{
return false;
}
var predecessor = path[runStartIndex - 1];
var predecessorDx = Math.Abs(runStart.X - predecessor.X);
var predecessorDy = Math.Abs(runStart.Y - predecessor.Y);
return side switch
{
"left" or "right" => predecessorDy > predecessorDx * 3d,
"top" or "bottom" => predecessorDx > predecessorDy * 3d,
_ => false,
};
}
private static bool IsOnWrongSideOfTarget(
ElkPoint point,
ElkPositionedNode targetNode,