暂时存一版

This commit is contained in:
艾竹
2023-02-04 11:16:39 +08:00
parent 848121ffa2
commit 8bec9b446f
10 changed files with 151 additions and 112 deletions

View File

@@ -771,6 +771,12 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set; get; set;
} }
[XmlAttribute]
public double Height
{
get; set;
}
[XmlAttribute] [XmlAttribute]
public ArrowPathStyle PathStyle public ArrowPathStyle PathStyle
{ {

View File

@@ -5,19 +5,57 @@ namespace AIStudio.Wpf.DiagramDesigner
public class PathGeneratorResult public class PathGeneratorResult
{ {
public PathGeneratorResult(string[] paths, double sourceMarkerAngle, PointBase sourceMarkerPosition, public PathGeneratorResult(string[] paths, double sourceMarkerAngle, PointBase sourceMarkerPosition,
double targetMarkerAngle, PointBase targetMarkerPosition) double targetMarkerAngle, PointBase targetMarkerPosition, PointBase[] route)
{ {
Paths = paths; Paths = paths;
SourceMarkerAngle = sourceMarkerAngle; SourceMarkerAngle = sourceMarkerAngle;
SourceMarkerPosition = sourceMarkerPosition; SourceMarkerPosition = sourceMarkerPosition;
TargetMarkerAngle = targetMarkerAngle; TargetMarkerAngle = targetMarkerAngle;
TargetMarkerPosition = targetMarkerPosition; TargetMarkerPosition = targetMarkerPosition;
Route = route;
} }
public string[] Paths { get; } public string[] Paths
public double SourceMarkerAngle { get; } {
public PointBase SourceMarkerPosition { get; } get;
public double TargetMarkerAngle { get; } }
public PointBase TargetMarkerPosition { get; } public double SourceMarkerAngle
{
get;
}
/// <summary>
/// SourceMarker左上角的点
/// </summary>
public PointBase SourceMarkerPosition
{
get;
}
public double TargetMarkerAngle
{
get;
}
/// <summary>
/// TargetMarker左上角的点
/// </summary>
public PointBase TargetMarkerPosition
{
get;
}
public PointBase[] Route
{
get;
}
public PointBase Last1
{
get => Route[Route.Length - 1];
}
public PointBase Last2
{
get => Route[Route.Length - 2];
}
} }
} }

View File

@@ -16,8 +16,8 @@ namespace AIStudio.Wpf.DiagramDesigner
route = GetRouteWithMiddlePoints(_, link, route); route = GetRouteWithMiddlePoints(_, link, route);
double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth()); double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth(), link.GetSourceMarkerHeight());
double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth()); double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth(), link.GetSinkMarkerHeight());
DoShift(route, link); DoShift(route, link);
@@ -27,7 +27,7 @@ namespace AIStudio.Wpf.DiagramDesigner
paths[i] = FormattableString.Invariant($"M {route[i].X} {route[i].Y} L {route[i + 1].X} {route[i + 1].Y}"); 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]); return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1], route);
} }
private static PointBase[] GetRouteWithMiddlePoints(IDiagramViewModel _, ConnectionViewModel link, PointBase[] route) private static PointBase[] GetRouteWithMiddlePoints(IDiagramViewModel _, ConnectionViewModel link, PointBase[] route)

View File

@@ -19,8 +19,8 @@ namespace AIStudio.Wpf.DiagramDesigner
else else
route = GetRouteWithPartConnectionLine(_, link, route); route = GetRouteWithPartConnectionLine(_, link, route);
double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth()); double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth(), link.GetSourceMarkerHeight());
double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth()); double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth(), link.GetSinkMarkerHeight());
DoShift(route, link); DoShift(route, link);
@@ -30,7 +30,7 @@ namespace AIStudio.Wpf.DiagramDesigner
paths[i] = FormattableString.Invariant($"M {route[i].X} {route[i].Y} L {route[i + 1].X} {route[i + 1].Y}"); 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]); return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1], route);
} }
private const int const_margin = 20; private const int const_margin = 20;

View File

@@ -17,19 +17,19 @@ namespace AIStudio.Wpf.DiagramDesigner
route = GetRouteWithCurvePoints(link, route); route = GetRouteWithCurvePoints(link, route);
double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth()); double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth(), link.GetSourceMarkerHeight());
double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth()); double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth(), link.GetSinkMarkerHeight());
DoShift(route, link); DoShift(route, link);
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}"); 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]); return new PathGeneratorResult(new[] { path }, sourceAngle, route[0], targetAngle, route[route.Length - 1], route);
} }
private static PathGeneratorResult CurveThroughPoints(PointBase[] route, ConnectionViewModel link) private static PathGeneratorResult CurveThroughPoints(PointBase[] route, ConnectionViewModel link)
{ {
double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth()); double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth(), link.GetSourceMarkerHeight());
double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth()); double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth(), link.GetSinkMarkerHeight());
BezierSpline.GetCurveControlPoints(route, out var firstControlPoints, out var secondControlPoints); BezierSpline.GetCurveControlPoints(route, out var firstControlPoints, out var secondControlPoints);
@@ -47,7 +47,7 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
// Todo: adjust marker positions based on closest control points // Todo: adjust marker positions based on closest control points
return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1]); return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1], route);
} }
private static PointBase[] GetRouteWithCurvePoints(ConnectionViewModel link, PointBase[] route) private static PointBase[] GetRouteWithCurvePoints(ConnectionViewModel link, PointBase[] route)

View File

@@ -9,8 +9,8 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
route = ConcatRouteAndSourceAndTarget(route, source, target); route = ConcatRouteAndSourceAndTarget(route, source, target);
double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth()); double sourceAngle = SourceMarkerAdjustement(route, link.GetSourceMarkerWidth(), link.GetSourceMarkerHeight());
double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth()); double targetAngle = TargetMarkerAdjustement(route, link.GetSinkMarkerWidth(), link.GetSinkMarkerHeight());
DoShift(route, link); DoShift(route, link);
@@ -20,7 +20,7 @@ namespace AIStudio.Wpf.DiagramDesigner
paths[i] = FormattableString.Invariant($"M {route[i].X} {route[i].Y} L {route[i + 1].X} {route[i + 1].Y}"); 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]); return new PathGeneratorResult(paths, sourceAngle, route[0], targetAngle, route[route.Length - 1], route);
} }
} }
} }

View File

@@ -6,7 +6,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{ {
public static partial class PathGenerators public static partial class PathGenerators
{ {
public static double SourceMarkerAdjustement(PointBase[] route, double markerWidth) public static double SourceMarkerAdjustement(PointBase[] route, double markerWidth, double markerHeight)
{ {
var angleInRadians = Math.Atan2(route[1].Y - route[0].Y, route[1].X - route[0].X) + Math.PI; var angleInRadians = Math.Atan2(route[1].Y - route[0].Y, route[1].X - route[0].X) + Math.PI;
var xChange = markerWidth * Math.Cos(angleInRadians); var xChange = markerWidth * Math.Cos(angleInRadians);
@@ -15,7 +15,7 @@ namespace AIStudio.Wpf.DiagramDesigner
return angleInRadians * 180 / Math.PI; return angleInRadians * 180 / Math.PI;
} }
public static double TargetMarkerAdjustement(PointBase[] route, double markerWidth) public static double TargetMarkerAdjustement(PointBase[] route, double markerWidth, double markerHeight)
{ {
var angleInRadians = Math.Atan2(route[route.Length - 1].Y - route[route.Length - 2].Y, route[route.Length - 1].X - route[route.Length - 2].X); var angleInRadians = Math.Atan2(route[route.Length - 1].Y - route[route.Length - 2].Y, route[route.Length - 1].X - route[route.Length - 2].X);
var xChange = markerWidth * Math.Cos(angleInRadians); var xChange = markerWidth * Math.Cos(angleInRadians);

View File

@@ -47,8 +47,6 @@
Data="{Binding ShapeViewModel.SinkMarker.Path}" Data="{Binding ShapeViewModel.SinkMarker.Path}"
Width="{Binding ShapeViewModel.SinkMarker.Width}" Width="{Binding ShapeViewModel.SinkMarker.Width}"
Stretch="UniformToFill" Stretch="UniformToFill"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderTransformOrigin="0.5,0.5" RenderTransformOrigin="0.5,0.5"
Visibility="{Binding Path=IsFullConnection, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" Visibility="{Binding Path=IsFullConnection, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
Style="{StaticResource ArrowStyle}"> Style="{StaticResource ArrowStyle}">
@@ -66,8 +64,6 @@
Canvas.Left="{Binding StartPoint.X}" Canvas.Left="{Binding StartPoint.X}"
Canvas.Top="{Binding StartPoint.Y}" Canvas.Top="{Binding StartPoint.Y}"
Stretch="UniformToFill" Stretch="UniformToFill"
HorizontalAlignment="Left"
VerticalAlignment="Top"
RenderTransformOrigin="0.5,0.5" RenderTransformOrigin="0.5,0.5"
Visibility="{Binding Path=IsFullConnection, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" Visibility="{Binding Path=IsFullConnection, Converter={x:Static s:BoolToVisibilityConverter.Instance}}"
Style="{StaticResource ArrowStyle}"> Style="{StaticResource ArrowStyle}">

View File

@@ -77,10 +77,10 @@ namespace AIStudio.Wpf.DiagramDesigner
public class LinkMarker : BindableBase, ILinkMarker public class LinkMarker : BindableBase, ILinkMarker
{ {
public static LinkMarker None { get; } = new LinkMarker("", 10, ArrowPathStyle.None, ArrowSizeStyle.Middle); public static LinkMarker None { get; } = new LinkMarker("", 10, 10, ArrowPathStyle.None, ArrowSizeStyle.Middle);
public static LinkMarker Arrow { get; } = new LinkMarker("M 0 -5 10 0 0 5 z", 10, ArrowPathStyle.Arrow, ArrowSizeStyle.Middle); public static LinkMarker Arrow { get; } = new LinkMarker("M 0 -5 10 0 0 5 z", 10, 10, ArrowPathStyle.Arrow, ArrowSizeStyle.Middle);
public static LinkMarker Circle { get; } = new LinkMarker("M 0, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0", 10, ArrowPathStyle.Circle, ArrowSizeStyle.Middle); public static LinkMarker Circle { get; } = new LinkMarker("M 0, 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0", 10, 10, ArrowPathStyle.Circle, ArrowSizeStyle.Middle);
public static LinkMarker Square { get; } = new LinkMarker("M 0 -5 10 -5 10 5 0 5 z", 10, ArrowPathStyle.Square, ArrowSizeStyle.Middle); public static LinkMarker Square { get; } = new LinkMarker("M 0 -5 10 -5 10 5 0 5 z", 10, 10, ArrowPathStyle.Square, ArrowSizeStyle.Middle);
public static readonly Dictionary<ArrowPathStyle, string> ArrowDictionary = new Dictionary<ArrowPathStyle, string>() public static readonly Dictionary<ArrowPathStyle, string> ArrowDictionary = new Dictionary<ArrowPathStyle, string>()
{ {
@@ -95,10 +95,11 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
public LinkMarker(string path, double width, ArrowPathStyle arrowPathStyle, ArrowSizeStyle arrowSizeStyle) public LinkMarker(string path, double width, double height, ArrowPathStyle arrowPathStyle, ArrowSizeStyle arrowSizeStyle)
{ {
Path = path; Path = path;
Width = width; Width = width;
Height = height;
_pathStyle = arrowPathStyle; _pathStyle = arrowPathStyle;
_sizeStyle = arrowSizeStyle; _sizeStyle = arrowSizeStyle;
} }
@@ -129,6 +130,19 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
} }
private double _height;
public double Height
{
get
{
return _height;
}
set
{
SetProperty(ref _height, value);
}
}
private ArrowPathStyle _pathStyle = ArrowPathStyle.None; private ArrowPathStyle _pathStyle = ArrowPathStyle.None;
public ArrowPathStyle PathStyle public ArrowPathStyle PathStyle
{ {
@@ -165,13 +179,13 @@ namespace AIStudio.Wpf.DiagramDesigner
} }
public static LinkMarker NewArrow(double width, double height) public static LinkMarker NewArrow(double width, double height)
=> new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} 0 0 {height / 2}"), width, ArrowPathStyle.Arrow, (ArrowSizeStyle)width); => new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} 0 0 {height / 2}"), width, height, ArrowPathStyle.Arrow, (ArrowSizeStyle)width);
public static LinkMarker NewCircle(double r) public static LinkMarker NewCircle(double r)
=> new LinkMarker(FormattableString.Invariant($"M 0, 0 a {r},{r} 0 1,0 {r * 2},0 a {r},{r} 0 1,0 -{r * 2},0"), r * 2, ArrowPathStyle.Circle, (ArrowSizeStyle)(r * 2)); => new LinkMarker(FormattableString.Invariant($"M 0, 0 a {r},{r} 0 1,0 {r * 2},0 a {r},{r} 0 1,0 -{r * 2},0"), r * 2, r * 2, ArrowPathStyle.Circle, (ArrowSizeStyle)(r * 2));
public static LinkMarker NewRectangle(double width, double height) public static LinkMarker NewRectangle(double width, double height)
=> new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} -{height / 2} {width} {height / 2} 0 {height / 2} z"), width, ArrowPathStyle.Square, (ArrowSizeStyle)width); => new LinkMarker(FormattableString.Invariant($"M 0 -{height / 2} {width} -{height / 2} {width} {height / 2} 0 {height / 2} z"), width, height, ArrowPathStyle.Square, (ArrowSizeStyle)width);
public static LinkMarker NewSquare(double size) => NewRectangle(size, size); public static LinkMarker NewSquare(double size) => NewRectangle(size, size);
} }
@@ -188,6 +202,11 @@ namespace AIStudio.Wpf.DiagramDesigner
get; set; get; set;
} }
double Height
{
get; set;
}
ArrowPathStyle PathStyle ArrowPathStyle PathStyle
{ {
get; set; get; set;

View File

@@ -520,74 +520,36 @@ namespace AIStudio.Wpf.DiagramDesigner
PathGeneratorResult = PathGenerator.Get(Root, this, route, source.Value, target.Value); PathGeneratorResult = PathGenerator.Get(Root, this, route, source.Value, target.Value);
if (IsFullConnection)
{
//修正旋转
switch (SourceConnectorInfo.Orientation)
{
case ConnectorOrientation.Left:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X, PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Top:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth() / 2, PathGeneratorResult.SourceMarkerPosition.Y);
break;
}
case ConnectorOrientation.Right:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth(), PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Bottom:
{
StartPoint = new PointBase(PathGeneratorResult.SourceMarkerPosition.X - GetSourceMarkerWidth() / 2, PathGeneratorResult.SourceMarkerPosition.Y - GetSourceMarkerWidth());
break;
}
default:
{
StartPoint = PathGeneratorResult.SourceMarkerPosition;
break;
}
}
//修正旋转 var offsetX = Math.Sin(EndAngle / 180 * Math.PI) * GetSinkMarkerWidth() / 2;
switch (SinkConnectorInfo.Orientation) var offsetY = Math.Cos(EndAngle / 180 * Math.PI) * GetSinkMarkerHeight() / 2;
{ if (PathGeneratorResult.Last1.X - PathGeneratorResult.Last2.X < -0.000001d)
case ConnectorOrientation.Left:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X, PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Top:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth() / 2, PathGeneratorResult.TargetMarkerPosition.Y);
break;
}
case ConnectorOrientation.Right:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth(), PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth() / 2);
break;
}
case ConnectorOrientation.Bottom:
{
EndPoint = new PointBase(PathGeneratorResult.TargetMarkerPosition.X - GetSinkMarkerWidth() / 2, PathGeneratorResult.TargetMarkerPosition.Y - GetSinkMarkerWidth());
break;
}
default:
{
EndPoint = PathGeneratorResult.TargetMarkerPosition;
break;
}
}
}
else
{ {
StartPoint = PathGeneratorResult.SourceMarkerPosition; offsetX += GetSinkMarkerWidth();
EndPoint = PathGeneratorResult.TargetMarkerPosition;
} }
if (PathGeneratorResult.Last1.Y - PathGeneratorResult.Last2.Y < -0.000001d)
{
offsetY += GetSinkMarkerHeight();
}
StartPoint = PathGeneratorResult.SourceMarkerPosition;
EndPoint = new PointBase
(
PathGeneratorResult.TargetMarkerPosition.X - Math.Abs(offsetX),
PathGeneratorResult.TargetMarkerPosition.Y - Math.Abs(offsetY)
);
//StartPoint = new PointBase
// (
// Math.Min(PathGeneratorResult.SourceMarkerPosition.X, source.Value.X),
// Math.Min(PathGeneratorResult.SourceMarkerPosition.Y, source.Value.Y)
// );
//EndPoint = new PointBase
// (
// Math.Min(PathGeneratorResult.TargetMarkerPosition.X, target.Value.X),
// Math.Min(PathGeneratorResult.TargetMarkerPosition.Y, target.Value.Y)
// );
StartAngle = PathGeneratorResult.SourceMarkerAngle; StartAngle = PathGeneratorResult.SourceMarkerAngle;
EndAngle = PathGeneratorResult.TargetMarkerAngle; EndAngle = PathGeneratorResult.TargetMarkerAngle;
@@ -625,7 +587,7 @@ namespace AIStudio.Wpf.DiagramDesigner
var sourceIntersection = GetClosestPointTo(sourceIntersections, firstPt); var sourceIntersection = GetClosestPointTo(sourceIntersections, firstPt);
var targetIntersection = GetClosestPointTo(targetIntersections, secondPt); var targetIntersection = GetClosestPointTo(targetIntersections, secondPt);
return (sourceIntersection ?? sourceCenter,targetIntersection ?? targetCenter); return (sourceIntersection ?? sourceCenter, targetIntersection ?? targetCenter);
} }
else else
{ {
@@ -697,22 +659,40 @@ namespace AIStudio.Wpf.DiagramDesigner
public double GetSourceMarkerWidth() public double GetSourceMarkerWidth()
{ {
if (string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path)) if (!IsFullConnection || string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path))
{ {
return 0; return 0;
} }
return ShapeViewModel.SourceMarker.Width; return ShapeViewModel.SourceMarker.Width;
} }
public double GetSourceMarkerHeight()
{
if (!IsFullConnection || string.IsNullOrEmpty(ShapeViewModel.SourceMarker.Path))
{
return 0;
}
return ShapeViewModel.SourceMarker.Height;
}
public double GetSinkMarkerWidth() public double GetSinkMarkerWidth()
{ {
if (string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path)) if (!IsFullConnection || string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path))
{ {
return 0; return 0;
} }
return ShapeViewModel.SinkMarker.Width; return ShapeViewModel.SinkMarker.Width;
} }
public double GetSinkMarkerHeight()
{
if (!IsFullConnection || string.IsNullOrEmpty(ShapeViewModel.SinkMarker.Path))
{
return 0;
}
return ShapeViewModel.SinkMarker.Height;
}
#region #region
private void AddVertex(object parameter) private void AddVertex(object parameter)
{ {