2023-01-14 21:52:05 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using AIStudio.Wpf.DiagramDesigner.Geometrys;
|
|
|
|
|
|
|
|
|
|
|
|
namespace AIStudio.Wpf.DiagramDesigner
|
|
|
|
|
|
{
|
|
|
|
|
|
public static partial class PathGenerators
|
|
|
|
|
|
{
|
|
|
|
|
|
public static PathGeneratorResult Boundary(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
|
|
|
|
|
|
{
|
|
|
|
|
|
route = ConcatRouteAndSourceAndTarget(route, source, target);
|
|
|
|
|
|
|
|
|
|
|
|
if (route.Length > 2)
|
|
|
|
|
|
return CurveThroughPoints(route, link);
|
|
|
|
|
|
|
|
|
|
|
|
route = GetRouteWithMiddlePoints(_, link, route);
|
|
|
|
|
|
|
2023-01-15 22:17:46 +08:00
|
|
|
|
double sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowSize);
|
|
|
|
|
|
double targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowSize);
|
2023-01-14 21:52:05 +08:00
|
|
|
|
|
|
|
|
|
|
DoShift(route, link);
|
|
|
|
|
|
|
|
|
|
|
|
var paths = new string[route.Length - 1];
|
|
|
|
|
|
for (var i = 0; i < route.Length - 1; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
paths[i] = FormattableString.Invariant($"M {route[i].X} {route[i].Y} L {route[i + 1].X} {route[i + 1].Y}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static PointBase[] GetRouteWithMiddlePoints(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route)
|
|
|
|
|
|
{
|
|
|
|
|
|
var middle = GetMiddlePoints(
|
2023-01-15 20:27:39 +08:00
|
|
|
|
link.SourceConnectorInfo.MiddlePosition,
|
2023-01-14 21:52:05 +08:00
|
|
|
|
link.SourceConnectorInfo.Orientation,
|
2023-01-15 20:27:39 +08:00
|
|
|
|
link.SinkConnectorInfo.MiddlePosition,
|
2023-01-15 22:17:46 +08:00
|
|
|
|
link.IsFullConnection ? link.SinkConnectorInfoFully.Orientation : (link.SinkConnectorInfo.MiddlePosition.Y >= link.SourceConnectorInfo.MiddlePosition.Y ? ConnectorOrientation.Top : ConnectorOrientation.Bottom),
|
2023-01-14 21:52:05 +08:00
|
|
|
|
_.GridCellSize,
|
|
|
|
|
|
_.GridMargin);
|
|
|
|
|
|
|
|
|
|
|
|
middle.Insert(0, route[0]);
|
|
|
|
|
|
middle.Add(route[1]);
|
|
|
|
|
|
|
|
|
|
|
|
return middle.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static List<PointBase> GetMiddlePoints(PointBase source, ConnectorOrientation sourceOrientation, PointBase sink, ConnectorOrientation sinkOrientation, SizeBase gridCellSize, double gridMargin)
|
|
|
|
|
|
{
|
|
|
|
|
|
var points = new List<PointBase>();
|
|
|
|
|
|
|
|
|
|
|
|
var p0 = GetFirstSegment(source, sourceOrientation, gridCellSize, gridMargin);
|
|
|
|
|
|
var p1 = GetFirstSegment(sink, sinkOrientation, gridCellSize, gridMargin);
|
|
|
|
|
|
|
|
|
|
|
|
if (p0 == p1)
|
|
|
|
|
|
return points;
|
|
|
|
|
|
|
|
|
|
|
|
var p2 = new PointBase(GetNearestCross(p0.X, p1.X, gridCellSize.Width, gridMargin), GetNearestCross(p0.Y, p1.Y, gridCellSize.Height, gridMargin));
|
|
|
|
|
|
var p3 = new PointBase(GetNearestCross(p1.X, p0.X, gridCellSize.Width, gridMargin), GetNearestCross(p1.Y, p0.Y, gridCellSize.Height, gridMargin));
|
|
|
|
|
|
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))
|
|
|
|
|
|
points.Add(new PointBase(p2.X, p3.Y));
|
|
|
|
|
|
points.Add(p3);
|
|
|
|
|
|
points.Add(p1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return points;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static PointBase GetFirstSegment(PointBase point, ConnectorOrientation orientation, SizeBase cellSize, double margin)
|
|
|
|
|
|
{
|
|
|
|
|
|
double x = ((int)((point.X - margin) / cellSize.Width) + 0.5) * cellSize.Width + margin;
|
|
|
|
|
|
double y = ((int)((point.Y - margin) / cellSize.Height) + 0.5) * cellSize.Height + margin;
|
|
|
|
|
|
if (orientation == ConnectorOrientation.Top)
|
|
|
|
|
|
return new PointBase(x, y - 0.5 * cellSize.Height);
|
|
|
|
|
|
else if (orientation == ConnectorOrientation.Bottom)
|
|
|
|
|
|
return new PointBase(x, y + 0.5 * cellSize.Height);
|
|
|
|
|
|
else if (orientation == ConnectorOrientation.Left)
|
|
|
|
|
|
return new PointBase(x - 0.5 * cellSize.Width, y);
|
|
|
|
|
|
else
|
|
|
|
|
|
return new PointBase(x + 0.5 * cellSize.Width, y);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static double GetNearestCross(double a, double b, double cellSize, double margin)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Math.Abs(a - b) < 0.0001 && (int)((a - margin)/ cellSize) == ((a - margin) / cellSize))
|
|
|
|
|
|
return a;
|
|
|
|
|
|
else if (a < b)
|
|
|
|
|
|
return Math.Ceiling((a - margin) / cellSize) * cellSize + margin;
|
|
|
|
|
|
else
|
|
|
|
|
|
return Math.Floor((a - margin) / cellSize) * cellSize + margin;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static PointBase SegmentMiddlePoint(PointBase p1, PointBase p2)
|
|
|
|
|
|
{
|
|
|
|
|
|
return new PointBase((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|