画线优化基本完成

This commit is contained in:
艾竹
2023-01-14 21:52:05 +08:00
parent 6a4c31106a
commit 717cc43827
23 changed files with 283 additions and 471 deletions

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class ConnectingLineBoundary : IPathGenerator
{
public PathGeneratorResult Get(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
{
return PathGenerators.Boundary(_, link, route, source, target);
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class ConnectingLineCorner : IPathGenerator
{
public PathGeneratorResult Get(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
{
return PathGenerators.Corner(_, link, route, source, target);
}
}
}

View File

@@ -5,7 +5,7 @@ using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class SmoothPathGenerator : IPathGenerator
public class ConnectingLineSmooth : IPathGenerator
{
public PathGeneratorResult Get(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
{

View File

@@ -5,7 +5,7 @@ using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class StraightPathGenerator : IPathGenerator
public class ConnectingLineStraight : IPathGenerator
{
public PathGeneratorResult Get(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
{

View File

@@ -0,0 +1,111 @@
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);
double? sourceAngle = null;
double? targetAngle = null;
sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowPathStyle == ArrowPathStyle.None ? 0d : (double)link.ColorViewModel.LeftArrowSizeStyle);
targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowPathStyle == ArrowPathStyle.None ? 0d : (double)link.ColorViewModel.RightArrowPathStyle);
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(
link.SourceConnectorInfo.Location.Position,
link.SourceConnectorInfo.Orientation,
link.SinkConnectorInfo.Location.Position,
link.IsFullConnection ? link.SinkConnectorInfoFully.Orientation : (link.SinkConnectorInfo.Location.Position.Y >= link.SourceConnectorInfo.Location.Position.Y ? ConnectorOrientation.Top : ConnectorOrientation.Bottom),
_.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);
}
}
}

View File

@@ -0,0 +1,648 @@
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 Corner(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
{
route = ConcatRouteAndSourceAndTarget(route, source, target);
if (route.Length > 2)
return CurveThroughPoints(route, link);
if (link.IsFullConnection)
route = GetRouteWithFullConnectionLine(_, link, route);
else
route = GetRouteWithPartConnectionLine(_, link, route);
double? sourceAngle = null;
double? targetAngle = null;
sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowPathStyle == ArrowPathStyle.None ? 0d : (double)link.ColorViewModel.LeftArrowSizeStyle);
targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowPathStyle == ArrowPathStyle.None ? 0d : (double)link.ColorViewModel.RightArrowPathStyle);
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 const int const_margin = 20;
private static PointBase[] GetRouteWithFullConnectionLine(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route)
{
var sourceInnerPoint = link.SourceConnectorInfo.IsInnerPoint;
PointBase sourcePoint = link.SourceConnectorInfo.Location.MiddlePosition;
PointBase sinkPoint = link.SinkConnectorInfo.Location.MiddlePosition;
ConnectorOrientation sourceOrientation = link.SourceConnectorInfo.Orientation;
ConnectorOrientation sinkOrientation = link.SinkConnectorInfoFully.Orientation;
List<PointBase> linePoints = new List<PointBase>();
int margin1 = sourceInnerPoint ? 0 : const_margin;
int margin2 = const_margin;
RectangleBase rectSource = GetRectWithMargin(sourcePoint, margin1);
RectangleBase rectSink = GetRectWithMargin(sinkPoint, margin2);
PointBase startPoint = GetOffsetPoint(sourcePoint, sourceOrientation, rectSource, sourceInnerPoint);
PointBase endPoint = GetOffsetPoint(sinkPoint, sinkOrientation, rectSink);
linePoints.Add(startPoint);
PointBase currentPoint = startPoint;
if (!rectSink.Contains(currentPoint) && !rectSource.Contains(endPoint))
{
while (true)
{
#region source node
if (IsPointVisible(currentPoint, endPoint, new RectangleBase[] { rectSource, rectSink }))
{
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
PointBase neighbour = GetNearestVisibleNeighborSink(currentPoint, endPoint, sinkOrientation, rectSource, rectSink);
if (!double.IsNaN(neighbour.X))
{
linePoints.Add(neighbour);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
if (currentPoint == startPoint)
{
bool flag;
PointBase n = GetNearestNeighborSource(sourceOrientation, endPoint, rectSource, rectSink, out flag, sourceInnerPoint);
if (linePoints.Contains(n))
{
break;
}
linePoints.Add(n);
currentPoint = n;
if (!IsRectVisible(currentPoint, rectSink, new RectangleBase[] { rectSource }))
{
PointBase n1, n2;
GetOppositeCorners(sourceOrientation, rectSource, out n1, out n2, sourceInnerPoint);
if (flag)
{
linePoints.Add(n1);
currentPoint = n1;
}
else
{
linePoints.Add(n2);
currentPoint = n2;
}
if (!IsRectVisible(currentPoint, rectSink, new RectangleBase[] { rectSource }))
{
if (flag)
{
linePoints.Add(n2);
currentPoint = n2;
}
else
{
linePoints.Add(n1);
currentPoint = n1;
}
}
}
}
#endregion
#region sink node
else // from here on we jump to the sink node
{
PointBase n1, n2; // neighbour corner
PointBase s1, s2; // opposite corner
GetNeighborCorners(sinkOrientation, rectSink, out s1, out s2);
GetOppositeCorners(sinkOrientation, rectSink, out n1, out n2);
bool n1Visible = IsPointVisible(currentPoint, n1, new RectangleBase[] { rectSource, rectSink });
bool n2Visible = IsPointVisible(currentPoint, n2, new RectangleBase[] { rectSource, rectSink });
if (n1Visible && n2Visible)
{
if (rectSource.Contains(n1))
{
linePoints.Add(n2);
if (rectSource.Contains(s2))
{
linePoints.Add(n1);
linePoints.Add(s1);
}
else
linePoints.Add(s2);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
if (rectSource.Contains(n2))
{
linePoints.Add(n1);
if (rectSource.Contains(s1))
{
linePoints.Add(n2);
linePoints.Add(s2);
}
else
linePoints.Add(s1);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
{
linePoints.Add(n1);
if (rectSource.Contains(s1))
{
linePoints.Add(n2);
linePoints.Add(s2);
}
else
linePoints.Add(s1);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
else
{
linePoints.Add(n2);
if (rectSource.Contains(s2))
{
linePoints.Add(n1);
linePoints.Add(s1);
}
else
linePoints.Add(s2);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
}
else if (n1Visible)
{
linePoints.Add(n1);
if (rectSource.Contains(s1))
{
linePoints.Add(n2);
linePoints.Add(s2);
}
else
linePoints.Add(s1);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
else
{
linePoints.Add(n2);
if (rectSource.Contains(s2))
{
linePoints.Add(n1);
linePoints.Add(s1);
}
else
linePoints.Add(s2);
linePoints.Add(endPoint);
currentPoint = endPoint;
break;
}
}
#endregion
}
}
else
{
linePoints.Add(endPoint);
}
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource, rectSink }, sourceOrientation, sinkOrientation);
linePoints.Insert(0, sourcePoint);
linePoints.Add(sinkPoint);
return linePoints.ToArray();
}
private static PointBase[] GetRouteWithPartConnectionLine(IDiagramViewModel diagramViewModel, ConnectorViewModel link, PointBase[] route)
{
var sourceInnerPoint = link.SourceConnectorInfo.IsInnerPoint;
PointBase sourcePoint = link.SourceConnectorInfo.Location.MiddlePosition;
PointBase sinkPoint = link.SinkConnectorInfo.Location.MiddlePosition;
ConnectorOrientation sourceOrientation = link.SourceConnectorInfo.Orientation;
ConnectorOrientation preferredOrientation = link.SourceConnectorInfo.Orientation;
List<PointBase> linePoints = new List<PointBase>();
int margin = sourceInnerPoint ? 0 : const_margin;
RectangleBase rectSource = GetRectWithMargin(sourcePoint, margin);
PointBase startPoint = GetOffsetPoint(sourcePoint, sourceOrientation, rectSource, sourceInnerPoint);
PointBase endPoint = sinkPoint;
linePoints.Add(startPoint);
PointBase currentPoint = startPoint;
if (!rectSource.Contains(endPoint))
{
while (true)
{
if (IsPointVisible(currentPoint, endPoint, new RectangleBase[] { rectSource }))
{
linePoints.Add(endPoint);
break;
}
bool sideFlag;
PointBase n = GetNearestNeighborSource(sourceOrientation, endPoint, rectSource, out sideFlag, sourceInnerPoint);
linePoints.Add(n);
currentPoint = n;
if (IsPointVisible(currentPoint, endPoint, new RectangleBase[] { rectSource }))
{
linePoints.Add(endPoint);
break;
}
else
{
PointBase n1, n2;
GetOppositeCorners(sourceOrientation, rectSource, out n1, out n2, sourceInnerPoint);
if (sideFlag)
linePoints.Add(n1);
else
linePoints.Add(n2);
linePoints.Add(endPoint);
break;
}
}
}
else
{
linePoints.Add(endPoint);
}
if (preferredOrientation != ConnectorOrientation.None)
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, sourceOrientation, preferredOrientation);
else
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, sourceOrientation, GetOpositeOrientation(sourceOrientation));
linePoints.Insert(0, sourcePoint);
return linePoints.ToArray();
}
private static List<PointBase> OptimizeLinePoints(List<PointBase> linePoints, RectangleBase[] rectangles, ConnectorOrientation sourceOrientation, ConnectorOrientation sinkOrientation)
{
List<PointBase> points = new List<PointBase>();
int cut = 0;
for (int i = 0; i < linePoints.Count; i++)
{
if (i >= cut)
{
for (int k = linePoints.Count - 1; k > i; k--)
{
if (IsPointVisible(linePoints[i], linePoints[k], rectangles))
{
cut = k;
break;
}
}
points.Add(linePoints[i]);
}
}
#region Line
for (int j = 0; j < points.Count - 1; j++)
{
if (points[j].X != points[j + 1].X && points[j].Y != points[j + 1].Y)
{
ConnectorOrientation orientationFrom;
ConnectorOrientation orientationTo;
// orientation from point
if (j == 0)
orientationFrom = sourceOrientation;
else
orientationFrom = GetOrientation(points[j], points[j - 1]);
// orientation to pint
if (j == points.Count - 2)
orientationTo = sinkOrientation;
else
orientationTo = GetOrientation(points[j + 1], points[j + 2]);
if ((orientationFrom == ConnectorOrientation.Left || orientationFrom == ConnectorOrientation.Right) &&
(orientationTo == ConnectorOrientation.Left || orientationTo == ConnectorOrientation.Right))
{
double centerX = Math.Min(points[j].X, points[j + 1].X) + Math.Abs(points[j].X - points[j + 1].X) / 2;
points.Insert(j + 1, new PointBase(centerX, points[j].Y));
points.Insert(j + 2, new PointBase(centerX, points[j + 2].Y));
if (points.Count - 1 > j + 3)
points.RemoveAt(j + 3);
return points;
}
if ((orientationFrom == ConnectorOrientation.Top || orientationFrom == ConnectorOrientation.Bottom) &&
(orientationTo == ConnectorOrientation.Top || orientationTo == ConnectorOrientation.Bottom))
{
double centerY = Math.Min(points[j].Y, points[j + 1].Y) + Math.Abs(points[j].Y - points[j + 1].Y) / 2;
points.Insert(j + 1, new PointBase(points[j].X, centerY));
points.Insert(j + 2, new PointBase(points[j + 2].X, centerY));
if (points.Count - 1 > j + 3)
points.RemoveAt(j + 3);
return points;
}
if ((orientationFrom == ConnectorOrientation.Left || orientationFrom == ConnectorOrientation.Right) &&
(orientationTo == ConnectorOrientation.Top || orientationTo == ConnectorOrientation.Bottom))
{
points.Insert(j + 1, new PointBase(points[j + 1].X, points[j].Y));
return points;
}
if ((orientationFrom == ConnectorOrientation.Top || orientationFrom == ConnectorOrientation.Bottom) &&
(orientationTo == ConnectorOrientation.Left || orientationTo == ConnectorOrientation.Right))
{
points.Insert(j + 1, new PointBase(points[j].X, points[j + 1].Y));
return points;
}
}
}
#endregion
return points;
}
private static ConnectorOrientation GetOrientation(PointBase p1, PointBase p2)
{
if (p1.X == p2.X)
{
if (p1.Y >= p2.Y)
return ConnectorOrientation.Bottom;
else
return ConnectorOrientation.Top;
}
else if (p1.Y == p2.Y)
{
if (p1.X >= p2.X)
return ConnectorOrientation.Right;
else
return ConnectorOrientation.Left;
}
throw new Exception("Failed to retrieve orientation");
}
private static PointBase GetNearestNeighborSource(ConnectorOrientation orientation, PointBase endPoint, RectangleBase rectSource, RectangleBase rectSink, out bool flag, bool isInnerPoint)
{
PointBase n1, n2; // neighbors
GetNeighborCorners(orientation, rectSource, out n1, out n2, isInnerPoint);
if (rectSink.Contains(n1))
{
flag = false;
return n2;
}
if (rectSink.Contains(n2))
{
flag = true;
return n1;
}
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
{
flag = true;
return n1;
}
else
{
flag = false;
return n2;
}
}
private static PointBase GetNearestNeighborSource(ConnectorOrientation orientation, PointBase endPoint, RectangleBase rectSource, out bool flag, bool isInnerPoint)
{
PointBase n1, n2; // neighbors
GetNeighborCorners(orientation, rectSource, out n1, out n2, isInnerPoint);
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
{
flag = true;
return n1;
}
else
{
flag = false;
return n2;
}
}
private static PointBase GetNearestVisibleNeighborSink(PointBase currentPoint, PointBase endPoint, ConnectorOrientation orientation, RectangleBase rectSource, RectangleBase rectSink)
{
PointBase s1, s2; // neighbors on sink side
GetNeighborCorners(orientation, rectSink, out s1, out s2);
bool flag1 = IsPointVisible(currentPoint, s1, new RectangleBase[] { rectSource, rectSink });
bool flag2 = IsPointVisible(currentPoint, s2, new RectangleBase[] { rectSource, rectSink });
if (flag1) // s1 visible
{
if (flag2) // s1 and s2 visible
{
if (rectSink.Contains(s1))
return s2;
if (rectSink.Contains(s2))
return s1;
if ((Distance(s1, endPoint) <= Distance(s2, endPoint)))
return s1;
else
return s2;
}
else
{
return s1;
}
}
else // s1 not visible
{
if (flag2) // only s2 visible
{
return s2;
}
else // s1 and s2 not visible
{
return new PointBase(double.NaN, double.NaN);
}
}
}
private static bool IsPointVisible(PointBase fromPoint, PointBase targetPoint, RectangleBase[] rectangles)
{
foreach (RectangleBase rect in rectangles)
{
if (RectangleIntersectsLine(rect, fromPoint, targetPoint))
return false;
}
return true;
}
private static bool IsRectVisible(PointBase fromPoint, RectangleBase targetRect, RectangleBase[] rectangles)
{
if (IsPointVisible(fromPoint, targetRect.TopLeft, rectangles))
return true;
if (IsPointVisible(fromPoint, targetRect.TopRight, rectangles))
return true;
if (IsPointVisible(fromPoint, targetRect.BottomLeft, rectangles))
return true;
if (IsPointVisible(fromPoint, targetRect.BottomRight, rectangles))
return true;
return false;
}
private static bool RectangleIntersectsLine(RectangleBase rect, PointBase startPoint, PointBase endPoint)
{
rect.Inflate(-1, -1);
return rect.IntersectsWith(new RectangleBase(startPoint, endPoint));
}
private static void GetOppositeCorners(ConnectorOrientation orientation, RectangleBase rect, out PointBase n1, out PointBase n2, bool isInnerPoint = false)
{
if (isInnerPoint)
{
n1 = rect.Location; n2 = rect.Location;
return;
}
switch (orientation)
{
case ConnectorOrientation.Left:
n1 = rect.TopRight; n2 = rect.BottomRight;
break;
case ConnectorOrientation.Top:
n1 = rect.BottomLeft; n2 = rect.BottomRight;
break;
case ConnectorOrientation.Right:
n1 = rect.TopLeft; n2 = rect.BottomLeft;
break;
case ConnectorOrientation.Bottom:
n1 = rect.TopLeft; n2 = rect.TopRight;
break;
default:
throw new Exception("No opposite corners found!");
}
}
private static void GetNeighborCorners(ConnectorOrientation orientation, RectangleBase rect, out PointBase n1, out PointBase n2, bool isInnerPoint = false)
{
if (isInnerPoint)
{
n1 = rect.Location; n2 = rect.Location;
return;
}
switch (orientation)
{
case ConnectorOrientation.Left:
n1 = rect.TopLeft; n2 = rect.BottomLeft;
break;
case ConnectorOrientation.Top:
n1 = rect.TopLeft; n2 = rect.TopRight;
break;
case ConnectorOrientation.Right:
n1 = rect.TopRight; n2 = rect.BottomRight;
break;
case ConnectorOrientation.Bottom:
n1 = rect.BottomLeft; n2 = rect.BottomRight;
break;
default:
throw new Exception("No neighour corners found!");
}
}
private static double Distance(PointBase p1, PointBase p2)
{
return PointBase.Subtract(p1, p2).Length;
}
private static RectangleBase GetRectWithMargin(PointBase point, double margin)
{
RectangleBase rect = new RectangleBase(point.X, point.Y, 0, 0);
rect.Inflate(margin, margin);
return rect;
}
private static PointBase GetOffsetPoint(PointBase point, ConnectorOrientation orientation, RectangleBase rect, bool isInnerPoint = false)
{
PointBase offsetPoint = new PointBase();
if (isInnerPoint)
{
offsetPoint = new PointBase(point.X, point.Y);
return offsetPoint;
}
switch (orientation)
{
case ConnectorOrientation.Left:
offsetPoint = new PointBase(rect.Left, point.Y);
break;
case ConnectorOrientation.Top:
offsetPoint = new PointBase(point.X, rect.Top);
break;
case ConnectorOrientation.Right:
offsetPoint = new PointBase(rect.Right, point.Y);
break;
case ConnectorOrientation.Bottom:
offsetPoint = new PointBase(point.X, rect.Bottom);
break;
default:
break;
}
return offsetPoint;
}
private static ConnectorOrientation GetOpositeOrientation(ConnectorOrientation connectorOrientation)
{
switch (connectorOrientation)
{
case ConnectorOrientation.Left:
return ConnectorOrientation.Right;
case ConnectorOrientation.Top:
return ConnectorOrientation.Bottom;
case ConnectorOrientation.Right:
return ConnectorOrientation.Left;
case ConnectorOrientation.Bottom:
return ConnectorOrientation.Top;
default:
return ConnectorOrientation.Top;
}
}
}
}

View File

@@ -19,8 +19,8 @@ namespace AIStudio.Wpf.DiagramDesigner
double? sourceAngle = null;
double? targetAngle = null;
sourceAngle = SourceMarkerAdjustement(route, (double)link.ColorViewModel.LeftArrowSizeStyle);
targetAngle = TargetMarkerAdjustement(route, (double)link.ColorViewModel.RightArrowPathStyle);
sourceAngle = SourceMarkerAdjustement(route, link.ColorViewModel.LeftArrowPathStyle == ArrowPathStyle.None ? 0d : (double)link.ColorViewModel.LeftArrowSizeStyle);
targetAngle = TargetMarkerAdjustement(route, link.ColorViewModel.RightArrowPathStyle == ArrowPathStyle.None ? 0d : (double)link.ColorViewModel.RightArrowPathStyle);
DoShift(route, link);