Files
aistudio-wpf-diagram/AIStudio.Wpf.DiagramDesigner/PathFinder/BoundaryPathFinder.cs

180 lines
7.3 KiB
C#
Raw Normal View History

2022-11-30 22:28:22 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
2023-01-08 09:22:37 +08:00
using AIStudio.Wpf.DiagramDesigner.Geometry;
2022-11-30 22:28:22 +08:00
namespace AIStudio.Wpf.DiagramDesigner
{
public class BoundaryPathFinder : IPathFinder
{
2023-01-08 09:22:37 +08:00
public List<ConnectorPoint> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, PointBase sourceA, PointBase sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
2022-11-30 22:28:22 +08:00
{
2023-01-08 09:22:37 +08:00
List<ConnectorPoint> connectionPoints;
2022-11-30 22:28:22 +08:00
var isFullConnection = sinkConnectorInfo is FullyCreatedConnectorInfo;
2023-01-08 09:22:37 +08:00
var points = new List<PointBase>()
2022-11-30 22:28:22 +08:00
{
sourceA,
sourceB
};
ConnectorInfo sourceInfo = ConnectorInfo(sourceConnectorInfo.Orientation,
points[0].X,
points[0].Y,
sourceConnectorInfo.DataItem.ItemWidth,
sourceConnectorInfo.DataItem.ItemHeight,
points[0]);
//StartPoint = points[0];
if (isFullConnection)
{
ConnectorInfo sinkInfo = ConnectorInfo(sinkConnectorInfo.Orientation,
points[1].X,
points[1].Y,
((FullyCreatedConnectorInfo)sinkConnectorInfo).DataItem.ItemWidth,
((FullyCreatedConnectorInfo)sinkConnectorInfo).DataItem.ItemHeight,
points[1]);
2023-01-08 09:22:37 +08:00
connectionPoints = ConnectorPoint.ToList(GetConnectionLine(diagramViewModel, sourceInfo, sinkInfo, false, sourceConnectorInfo.IsInnerPoint));
2022-11-30 22:28:22 +08:00
//EndPoint = ConnectionPoints.Last();
}
else
{
2023-01-08 09:22:37 +08:00
connectionPoints = ConnectorPoint.ToList(GetConnectionLine(diagramViewModel, sourceInfo, points[1], sourceConnectorInfo.Orientation, false, sourceConnectorInfo.IsInnerPoint));
//EndPoint = new PointBase();
2022-11-30 22:28:22 +08:00
}
return connectionPoints;
}
2023-01-08 09:22:37 +08:00
public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, PointBase position)
2022-11-30 22:28:22 +08:00
{
return new ConnectorInfo()
{
Orientation = orientation,
2023-01-08 09:22:37 +08:00
DesignerItemSize = new SizeBase(width, height),
2022-11-30 22:28:22 +08:00
DesignerItemLeft = left,
DesignerItemTop = top,
Position = position
};
}
2023-01-08 09:22:37 +08:00
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
2022-11-30 22:28:22 +08:00
{
2023-01-08 09:22:37 +08:00
var points = new List<PointBase>();
var ends = new List<PointBase> { source.Position, sink.Position };
2022-11-30 22:28:22 +08:00
points.Add(ends[0]);
points.AddRange(GetMiddlePoints(source, sink, diagramViewModel.GridCellSize, diagramViewModel.GridMargin, true));
points.Add(ends[1]);
var res = points.ToArray();
DoShift(res);
return res.ToList();
}
2023-01-08 09:22:37 +08:00
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, PointBase sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
2022-11-30 22:28:22 +08:00
{
2023-01-08 09:22:37 +08:00
var points = new List<PointBase>();
var ends = new List<PointBase> { source.Position, sinkPoint };
2022-11-30 22:28:22 +08:00
points.Add(ends[0]);
points.AddRange(GetMiddlePoints(source, new ConnectorInfo() { Orientation = ConnectorOrientation.Top, Position = sinkPoint }, diagramViewModel.GridCellSize, diagramViewModel.GridMargin, false));
points.Add(ends[1]);
var res = points.ToArray();
DoShift(res);
return res.ToList();
}
2023-01-08 09:22:37 +08:00
private IEnumerable<PointBase> GetMiddlePoints(ConnectorInfo source, ConnectorInfo sink, SizeBase gridCellSize, double gridMargin, bool isFullConnection)
2022-11-30 22:28:22 +08:00
{
2023-01-08 09:22:37 +08:00
var points = new List<PointBase>();
2022-11-30 22:28:22 +08:00
if (isFullConnection)
{
var p0 = GetFirstSegment(source.Orientation, source.Position, gridCellSize, gridMargin);
var p1 = GetFirstSegment(sink.Orientation, sink.Position, gridCellSize, gridMargin);
if (p0 == p1)
return points;
2023-01-08 09:22:37 +08:00
var p2 = new PointBase(GetNearestCross(p0.X, p1.X), GetNearestCross(p0.Y, p1.Y));
var p3 = new PointBase(GetNearestCross(p1.X, p0.X), GetNearestCross(p1.Y, p0.Y));
2022-11-30 22:28:22 +08:00
if (p2 == p3)
{
points.Add(p0);
points.Add(p2);
points.Add(p1);
}
else
{
points.Add(p0);
points.Add(p2);
if (!(Math.Abs(p2.X - p3.X) < 0.0001) && !(Math.Abs(p2.Y - p3.Y) < 0.0001))
2023-01-08 09:22:37 +08:00
points.Add(new PointBase(p2.X, p3.Y));
2022-11-30 22:28:22 +08:00
points.Add(p3);
points.Add(p1);
}
DoScale(points, gridCellSize, gridMargin);
}
return points;
}
2023-01-08 09:22:37 +08:00
private PointBase GetFirstSegment(ConnectorOrientation orientation, PointBase point, SizeBase cellSize, double margin)
2022-11-30 22:28:22 +08:00
{
double x = (int)((point.X - margin) / cellSize.Width) + 0.5;
double y = (int)((point.Y - margin) / cellSize.Height) + 0.5;
if (orientation == ConnectorOrientation.Top)
2023-01-08 09:22:37 +08:00
return new PointBase(x, y - 0.5);
2022-11-30 22:28:22 +08:00
else if (orientation == ConnectorOrientation.Bottom)
2023-01-08 09:22:37 +08:00
return new PointBase(x, y + 0.5);
2022-11-30 22:28:22 +08:00
else if (orientation == ConnectorOrientation.Left)
2023-01-08 09:22:37 +08:00
return new PointBase(x - 0.5, y);
2022-11-30 22:28:22 +08:00
else
2023-01-08 09:22:37 +08:00
return new PointBase(x + 0.5, y);
2022-11-30 22:28:22 +08:00
}
public static double GetNearestCross(double a, double b)
{
if (Math.Abs(a - b) < 0.0001 && (int)a == a)
return a;
else if (a < b)
return Math.Ceiling(a);
else
return Math.Floor(a);
}
2023-01-08 09:22:37 +08:00
public static PointBase SegmentMiddlePoint(PointBase p1, PointBase p2)
2022-11-30 22:28:22 +08:00
{
2023-01-08 09:22:37 +08:00
return new PointBase((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
2022-11-30 22:28:22 +08:00
}
2023-01-08 09:22:37 +08:00
private void DoScale(List<PointBase> points, SizeBase cellSize, double margin)
2022-11-30 22:28:22 +08:00
{
for (int i = 0; i < points.Count; i++)
{
2023-01-08 09:22:37 +08:00
points[i] = new PointBase(points[i].X * cellSize.Width + margin,
2022-11-30 22:28:22 +08:00
points[i].Y * cellSize.Height + margin);
}
}
2023-01-08 09:22:37 +08:00
private void DoShift(PointBase[] points)
2022-11-30 22:28:22 +08:00
{
2023-01-08 09:22:37 +08:00
double left = new PointBase[] { points.FirstOrDefault(), points.LastOrDefault() }.Min(p => p.X);
double top = new PointBase[] { points.FirstOrDefault(), points.LastOrDefault() }.Min(p => p.Y);
2022-11-30 22:28:22 +08:00
for (int i = 0; i < points.Length; i++)
{
points[i].X = points[i].X - left;
points[i].Y = points[i].Y - top;
}
}
}
}