mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-20 08:26:36 +08:00
使用PointBase代替Point
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using AIStudio.Wpf.DiagramDesigner.Geometry;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public static partial class PathGenerators
|
||||
{
|
||||
private const double _margin = 125;
|
||||
|
||||
public static PathGeneratorResult Smooth(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
|
||||
{
|
||||
route = ConcatRouteAndSourceAndTarget(route, source, target);
|
||||
|
||||
if (route.Length > 2)
|
||||
return CurveThroughPoints(route, link);
|
||||
|
||||
route = GetRouteWithCurvePoints(link, route);
|
||||
double? sourceAngle = null;
|
||||
double? targetAngle = null;
|
||||
|
||||
sourceAngle = SourceMarkerAdjustement(route, (double)link.ColorViewModel.LeftArrowSizeStyle);
|
||||
targetAngle = TargetMarkerAdjustement(route, (double)link.ColorViewModel.RightArrowPathStyle);
|
||||
|
||||
var path = FormattableString.Invariant($"M {route[0].X} {route[0].Y} C {route[1].X} {route[1].Y}, {route[2].X} {route[2].Y}, {route[3].X} {route[3].Y}");
|
||||
return new PathGeneratorResult(new[] { path }, sourceAngle, route[0], targetAngle, route[route.Length - 1]);
|
||||
}
|
||||
|
||||
private static PathGeneratorResult CurveThroughPoints(PointBase[] route, ConnectorViewModel link)
|
||||
{
|
||||
double? sourceAngle = null;
|
||||
double? targetAngle = null;
|
||||
|
||||
sourceAngle = SourceMarkerAdjustement(route, (double)link.ColorViewModel.LeftArrowSizeStyle);
|
||||
targetAngle = TargetMarkerAdjustement(route, (double)link.ColorViewModel.RightArrowPathStyle);
|
||||
|
||||
Geometry.BezierSpline.GetCurveControlPoints(route, out var firstControlPoints, out var secondControlPoints);
|
||||
var paths = new string[firstControlPoints.Length];
|
||||
|
||||
for (var i = 0; i < firstControlPoints.Length; i++)
|
||||
{
|
||||
var cp1 = firstControlPoints[i];
|
||||
var cp2 = secondControlPoints[i];
|
||||
paths[i] = FormattableString.Invariant($"M {route[i].X} {route[i].Y} C {cp1.X} {cp1.Y}, {cp2.X} {cp2.Y}, {route[i + 1].X} {route[i + 1].Y}");
|
||||
}
|
||||
|
||||
// Todo: adjust marker positions based on closest control points
|
||||
return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1]);
|
||||
}
|
||||
|
||||
private static PointBase[] GetRouteWithCurvePoints(ConnectorViewModel link, PointBase[] route)
|
||||
{
|
||||
if (link.IsPortless)
|
||||
{
|
||||
if (Math.Abs(route[0].X - route[1].X) >= Math.Abs(route[0].Y - route[1].Y))
|
||||
{
|
||||
var cX = (route[0].X + route[1].X) / 2;
|
||||
return new[] { route[0], new PointBase(cX, route[0].Y), new PointBase(cX, route[1].Y), route[1] };
|
||||
}
|
||||
else
|
||||
{
|
||||
var cY = (route[0].Y + route[1].Y) / 2;
|
||||
return new[] { route[0], new PointBase(route[0].X, cY), new PointBase(route[1].X, cY), route[1] };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var cX = (route[0].X + route[1].X) / 2;
|
||||
var cY = (route[0].Y + route[1].Y) / 2;
|
||||
var curvePointA = GetCurvePoint(route[0].X, route[0].Y, cX, cY, link.SourceConnectorInfo?.Orientation);
|
||||
var curvePointB = GetCurvePoint(route[1].X, route[1].Y, cX, cY, link.SinkConnectorInfo?.Orientation);
|
||||
return new[] { route[0], curvePointA, curvePointB, route[1] };
|
||||
}
|
||||
}
|
||||
|
||||
private static PointBase GetCurvePoint(double pX, double pY, double cX, double cY, ConnectorOrientation? alignment)
|
||||
{
|
||||
var margin = Math.Min(_margin, Math.Pow(Math.Pow(pX - cX, 2) + Math.Pow(pY - cY, 2), .5));
|
||||
switch (alignment)
|
||||
{
|
||||
case ConnectorOrientation.Top: return new PointBase(pX, Math.Min(pY - margin, cY));
|
||||
case ConnectorOrientation.Bottom: return new PointBase(pX, Math.Max(pY + margin, cY));
|
||||
case ConnectorOrientation.TopRight: return new PointBase(Math.Max(pX + margin, cX), Math.Min(pY - margin, cY));
|
||||
case ConnectorOrientation.BottomRight: return new PointBase(Math.Max(pX + margin, cX), Math.Max(pY + margin, cY));
|
||||
case ConnectorOrientation.Right: return new PointBase(Math.Max(pX + margin, cX), pY);
|
||||
case ConnectorOrientation.Left: return new PointBase(Math.Min(pX - margin, cX), pY);
|
||||
case ConnectorOrientation.BottomLeft: return new PointBase(Math.Min(pX - margin, cX), Math.Max(pY + margin, cY));
|
||||
case ConnectorOrientation.TopLeft: return new PointBase(Math.Min(pX - margin, cX), Math.Min(pY - margin, cY));
|
||||
default: return new PointBase(cX, cY);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user