110 lines
3.3 KiB
C#
110 lines
3.3 KiB
C#
namespace StellaOps.ElkSharp;
|
|
|
|
internal static partial class ElkEdgeRoutingGeometry
|
|
{
|
|
private const double CoordinateTolerance = 0.5d;
|
|
|
|
internal static IReadOnlyList<RoutedEdgeSegment> FlattenSegments(IReadOnlyCollection<ElkRoutedEdge> edges)
|
|
{
|
|
var segments = new List<RoutedEdgeSegment>();
|
|
foreach (var edge in edges)
|
|
{
|
|
segments.AddRange(FlattenSegments(edge));
|
|
}
|
|
|
|
return segments;
|
|
}
|
|
|
|
internal static IReadOnlyList<RoutedEdgeSegment> FlattenSegments(ElkRoutedEdge edge)
|
|
{
|
|
var segments = new List<RoutedEdgeSegment>();
|
|
foreach (var section in edge.Sections)
|
|
{
|
|
var points = new List<ElkPoint> { section.StartPoint };
|
|
points.AddRange(section.BendPoints);
|
|
points.Add(section.EndPoint);
|
|
|
|
for (var i = 0; i < points.Count - 1; i++)
|
|
{
|
|
segments.Add(new RoutedEdgeSegment(edge.Id, points[i], points[i + 1]));
|
|
}
|
|
}
|
|
|
|
return segments;
|
|
}
|
|
|
|
internal static double ComputePathLength(ElkRoutedEdge edge)
|
|
{
|
|
return FlattenSegments(edge).Sum(segment => ComputeSegmentLength(segment.Start, segment.End));
|
|
}
|
|
|
|
internal static double ComputeSegmentLength(ElkPoint start, ElkPoint end)
|
|
{
|
|
var dx = end.X - start.X;
|
|
var dy = end.Y - start.Y;
|
|
return Math.Sqrt((dx * dx) + (dy * dy));
|
|
}
|
|
|
|
internal static double ComputeLongestSharedSegmentLength(ElkRoutedEdge left, ElkRoutedEdge right)
|
|
{
|
|
var leftSegments = FlattenSegments(left);
|
|
var rightSegments = FlattenSegments(right);
|
|
var longest = 0d;
|
|
|
|
foreach (var leftSegment in leftSegments)
|
|
{
|
|
foreach (var rightSegment in rightSegments)
|
|
{
|
|
longest = Math.Max(longest, ComputeSharedSegmentLength(
|
|
leftSegment.Start,
|
|
leftSegment.End,
|
|
rightSegment.Start,
|
|
rightSegment.End));
|
|
}
|
|
}
|
|
|
|
return longest;
|
|
}
|
|
|
|
internal static double ComputeLongestSharedApproachSegmentLength(
|
|
IReadOnlyList<ElkPoint> leftPath,
|
|
IReadOnlyList<ElkPoint> rightPath,
|
|
int maxSegmentsFromEnd = 3)
|
|
{
|
|
var leftSegments = FlattenSegmentsNearEnd(leftPath, maxSegmentsFromEnd);
|
|
var rightSegments = FlattenSegmentsNearEnd(rightPath, maxSegmentsFromEnd);
|
|
var longest = 0d;
|
|
|
|
foreach (var leftSegment in leftSegments)
|
|
{
|
|
foreach (var rightSegment in rightSegments)
|
|
{
|
|
longest = Math.Max(longest, ComputeSharedSegmentLength(
|
|
leftSegment.Start,
|
|
leftSegment.End,
|
|
rightSegment.Start,
|
|
rightSegment.End));
|
|
}
|
|
}
|
|
|
|
return longest;
|
|
}
|
|
|
|
internal static ElkPoint ResolveApproachPoint(ElkRoutedEdge edge)
|
|
{
|
|
var lastSection = edge.Sections.Last();
|
|
if (lastSection.BendPoints.Count > 0)
|
|
{
|
|
return lastSection.BendPoints.Last();
|
|
}
|
|
|
|
return lastSection.StartPoint;
|
|
}
|
|
|
|
internal static bool PointsEqual(ElkPoint left, ElkPoint right)
|
|
{
|
|
return Math.Abs(left.X - right.X) <= CoordinateTolerance
|
|
&& Math.Abs(left.Y - right.Y) <= CoordinateTolerance;
|
|
}
|
|
}
|