mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-04-09 02:36:35 +08:00
使用PointBase代替Point
This commit is contained in:
@@ -1,180 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public class BoundaryPathFinder : IPathFinder
|
||||
{
|
||||
public List<PointInfoBase> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, Point sourceA, Point sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
|
||||
{
|
||||
List<PointInfoBase> connectionPoints;
|
||||
var isFullConnection = sinkConnectorInfo is FullyCreatedConnectorInfo;
|
||||
|
||||
var points = new List<Point>()
|
||||
{
|
||||
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]);
|
||||
|
||||
connectionPoints = PointInfoBase.ToList(GetConnectionLine(diagramViewModel, sourceInfo, sinkInfo, false, sourceConnectorInfo.IsInnerPoint));
|
||||
//EndPoint = ConnectionPoints.Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionPoints = PointInfoBase.ToList(GetConnectionLine(diagramViewModel, sourceInfo, points[1], sourceConnectorInfo.Orientation, false, sourceConnectorInfo.IsInnerPoint));
|
||||
//EndPoint = new Point();
|
||||
}
|
||||
|
||||
return connectionPoints;
|
||||
}
|
||||
|
||||
public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, Point position)
|
||||
{
|
||||
return new ConnectorInfo()
|
||||
{
|
||||
Orientation = orientation,
|
||||
DesignerItemSize = new Size(width, height),
|
||||
DesignerItemLeft = left,
|
||||
DesignerItemTop = top,
|
||||
Position = position
|
||||
};
|
||||
}
|
||||
|
||||
public List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
|
||||
{
|
||||
var points = new List<Point>();
|
||||
var ends = new List<Point> { source.Position, sink.Position };
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, Point sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
|
||||
{
|
||||
var points = new List<Point>();
|
||||
var ends = new List<Point> { source.Position, sinkPoint };
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private IEnumerable<Point> GetMiddlePoints(ConnectorInfo source, ConnectorInfo sink, Size gridCellSize, double gridMargin, bool isFullConnection)
|
||||
{
|
||||
var points = new List<Point>();
|
||||
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;
|
||||
|
||||
|
||||
var p2 = new Point(GetNearestCross(p0.X, p1.X), GetNearestCross(p0.Y, p1.Y));
|
||||
var p3 = new Point(GetNearestCross(p1.X, p0.X), GetNearestCross(p1.Y, p0.Y));
|
||||
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 Point(p2.X, p3.Y));
|
||||
points.Add(p3);
|
||||
points.Add(p1);
|
||||
}
|
||||
DoScale(points, gridCellSize, gridMargin);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
private Point GetFirstSegment(ConnectorOrientation orientation, Point point, Size cellSize, double margin)
|
||||
{
|
||||
double x = (int)((point.X - margin) / cellSize.Width) + 0.5;
|
||||
double y = (int)((point.Y - margin) / cellSize.Height) + 0.5;
|
||||
if (orientation == ConnectorOrientation.Top)
|
||||
return new Point(x, y - 0.5);
|
||||
else if (orientation == ConnectorOrientation.Bottom)
|
||||
return new Point(x, y + 0.5);
|
||||
else if (orientation == ConnectorOrientation.Left)
|
||||
return new Point(x - 0.5, y);
|
||||
else
|
||||
return new Point(x + 0.5, y);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static Point SegmentMiddlePoint(Point p1, Point p2)
|
||||
{
|
||||
return new Point((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
|
||||
}
|
||||
|
||||
|
||||
private void DoScale(List<Point> points, Size cellSize, double margin)
|
||||
{
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
points[i] = new Point(points[i].X * cellSize.Width + margin,
|
||||
points[i].Y * cellSize.Height + margin);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoShift(Point[] points)
|
||||
{
|
||||
double left = new Point[] { points.FirstOrDefault(), points.LastOrDefault() }.Min(p => p.X);
|
||||
double top = new Point[] { points.FirstOrDefault(), points.LastOrDefault() }.Min(p => p.Y);
|
||||
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
points[i].X = points[i].X - left;
|
||||
points[i].Y = points[i].Y - top;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public interface IPathFinder
|
||||
{
|
||||
List<PointInfoBase> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, Point sourceA, Point sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo);
|
||||
List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false);
|
||||
List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, Point sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false);
|
||||
}
|
||||
}
|
||||
@@ -1,751 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
// Note: I couldn't find a useful open source library that does
|
||||
// orthogonal routing so started to write something on my own.
|
||||
// Categorize this as a quick and dirty short term solution.
|
||||
// I will keep on searching.
|
||||
|
||||
// Helper class to provide an orthogonal connection path
|
||||
public class OrthogonalPathFinder : IPathFinder
|
||||
{
|
||||
private const int const_margin = 20;
|
||||
|
||||
public List<PointInfoBase> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, Point sourceA, Point sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
|
||||
{
|
||||
List<PointInfoBase> connectionPoints;
|
||||
var isFullConnection = sinkConnectorInfo is FullyCreatedConnectorInfo;
|
||||
var area = new Rect(sourceA, sourceB);
|
||||
|
||||
var points = new List<Point>()
|
||||
{
|
||||
new Point(sourceA.X < sourceB.X ? 0d : area.Width, sourceA.Y < sourceB.Y ? 0d : area.Height ),
|
||||
new Point(sourceA.X > sourceB.X ? 0d : area.Width, sourceA.Y > sourceB.Y ? 0d : area.Height)
|
||||
};
|
||||
|
||||
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]);
|
||||
|
||||
connectionPoints = PointInfoBase.ToList(GetConnectionLine(diagramViewModel, sourceInfo, sinkInfo, false, sourceConnectorInfo.IsInnerPoint));
|
||||
//EndPoint = ConnectionPoints.Last();
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionPoints = PointInfoBase.ToList(GetConnectionLine(diagramViewModel, sourceInfo, points[1], sourceConnectorInfo.Orientation, false, sourceConnectorInfo.IsInnerPoint));
|
||||
//EndPoint = new Point();
|
||||
}
|
||||
|
||||
return connectionPoints;
|
||||
}
|
||||
|
||||
public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, Point position)
|
||||
{
|
||||
return new ConnectorInfo()
|
||||
{
|
||||
Orientation = orientation,
|
||||
DesignerItemSize = new Size(width, height),
|
||||
DesignerItemLeft = left,
|
||||
DesignerItemTop = top,
|
||||
Position = position
|
||||
};
|
||||
}
|
||||
|
||||
public List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
|
||||
{
|
||||
List<Point> linePoints = new List<Point>();
|
||||
int margin1 = sourceInnerPoint ? 0 : const_margin;
|
||||
int margin2 = const_margin;
|
||||
|
||||
Rect rectSource = GetRectWithMargin(source, margin1);
|
||||
Rect rectSink = GetRectWithMargin(sink, margin2);
|
||||
|
||||
Point startPoint = GetOffsetPoint(source, rectSource, sourceInnerPoint);
|
||||
Point endPoint = GetOffsetPoint(sink, rectSink);
|
||||
|
||||
linePoints.Add(startPoint);
|
||||
Point currentPoint = startPoint;
|
||||
|
||||
if (!rectSink.Contains(currentPoint) && !rectSource.Contains(endPoint))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
#region source node
|
||||
|
||||
if (IsPointVisible(currentPoint, endPoint, new Rect[] { rectSource, rectSink }))
|
||||
{
|
||||
linePoints.Add(endPoint);
|
||||
currentPoint = endPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
Point neighbour = GetNearestVisibleNeighborSink(currentPoint, endPoint, sink, rectSource, rectSink);
|
||||
if (!double.IsNaN(neighbour.X))
|
||||
{
|
||||
linePoints.Add(neighbour);
|
||||
linePoints.Add(endPoint);
|
||||
currentPoint = endPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentPoint == startPoint)
|
||||
{
|
||||
bool flag;
|
||||
Point n = GetNearestNeighborSource(source, endPoint, rectSource, rectSink, out flag, sourceInnerPoint);
|
||||
if (linePoints.Contains(n))
|
||||
{
|
||||
break;
|
||||
}
|
||||
linePoints.Add(n);
|
||||
currentPoint = n;
|
||||
|
||||
if (!IsRectVisible(currentPoint, rectSink, new Rect[] { rectSource }))
|
||||
{
|
||||
Point n1, n2;
|
||||
GetOppositeCorners(source.Orientation, rectSource, out n1, out n2, sourceInnerPoint);
|
||||
if (flag)
|
||||
{
|
||||
linePoints.Add(n1);
|
||||
currentPoint = n1;
|
||||
}
|
||||
else
|
||||
{
|
||||
linePoints.Add(n2);
|
||||
currentPoint = n2;
|
||||
}
|
||||
if (!IsRectVisible(currentPoint, rectSink, new Rect[] { 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
|
||||
{
|
||||
Point n1, n2; // neighbour corner
|
||||
Point s1, s2; // opposite corner
|
||||
GetNeighborCorners(sink.Orientation, rectSink, out s1, out s2);
|
||||
GetOppositeCorners(sink.Orientation, rectSink, out n1, out n2);
|
||||
|
||||
bool n1Visible = IsPointVisible(currentPoint, n1, new Rect[] { rectSource, rectSink });
|
||||
bool n2Visible = IsPointVisible(currentPoint, n2, new Rect[] { 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 Rect[] { rectSource, rectSink }, source.Orientation, sink.Orientation);
|
||||
|
||||
CheckPathEnd(source, sink, showLastLine, linePoints, sourceInnerPoint);
|
||||
|
||||
return linePoints;
|
||||
}
|
||||
|
||||
public List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, Point sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
|
||||
{
|
||||
List<Point> linePoints = new List<Point>();
|
||||
int margin = isInnerPoint ? 0 : const_margin;
|
||||
|
||||
Rect rectSource = GetRectWithMargin(source, margin);
|
||||
Point startPoint = GetOffsetPoint(source, rectSource, isInnerPoint);
|
||||
Point endPoint = sinkPoint;
|
||||
|
||||
linePoints.Add(startPoint);
|
||||
Point currentPoint = startPoint;
|
||||
|
||||
if (!rectSource.Contains(endPoint))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (IsPointVisible(currentPoint, endPoint, new Rect[] { rectSource }))
|
||||
{
|
||||
linePoints.Add(endPoint);
|
||||
break;
|
||||
}
|
||||
|
||||
bool sideFlag;
|
||||
Point n = GetNearestNeighborSource(source, endPoint, rectSource, out sideFlag, isInnerPoint);
|
||||
linePoints.Add(n);
|
||||
currentPoint = n;
|
||||
|
||||
if (IsPointVisible(currentPoint, endPoint, new Rect[] { rectSource }))
|
||||
{
|
||||
linePoints.Add(endPoint);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Point n1, n2;
|
||||
GetOppositeCorners(source.Orientation, rectSource, out n1, out n2, isInnerPoint);
|
||||
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 Rect[] { rectSource }, source.Orientation, preferredOrientation);
|
||||
else
|
||||
linePoints = OptimizeLinePoints(linePoints, new Rect[] { rectSource }, source.Orientation, GetOpositeOrientation(source.Orientation));
|
||||
|
||||
if (!showLastLine)
|
||||
{
|
||||
linePoints.Insert(0, source.Position);
|
||||
}
|
||||
|
||||
return linePoints;
|
||||
}
|
||||
|
||||
private static List<Point> OptimizeLinePoints(List<Point> linePoints, Rect[] rectangles, ConnectorOrientation sourceOrientation, ConnectorOrientation sinkOrientation)
|
||||
{
|
||||
List<Point> points = new List<Point>();
|
||||
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 Point(centerX, points[j].Y));
|
||||
points.Insert(j + 2, new Point(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 Point(points[j].X, centerY));
|
||||
points.Insert(j + 2, new Point(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 Point(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 Point(points[j].X, points[j + 1].Y));
|
||||
return points;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
private static ConnectorOrientation GetOrientation(Point p1, Point 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 Orientation GetOrientation(ConnectorOrientation sourceOrientation, bool isInnerPoint)
|
||||
{
|
||||
if (isInnerPoint)
|
||||
{
|
||||
return Orientation.Vertical;
|
||||
}
|
||||
switch (sourceOrientation)
|
||||
{
|
||||
case ConnectorOrientation.Left:
|
||||
return Orientation.Horizontal;
|
||||
case ConnectorOrientation.Top:
|
||||
return Orientation.Vertical;
|
||||
case ConnectorOrientation.Right:
|
||||
return Orientation.Horizontal;
|
||||
case ConnectorOrientation.Bottom:
|
||||
return Orientation.Vertical;
|
||||
default:
|
||||
throw new Exception("Unknown ConnectorOrientation");
|
||||
}
|
||||
}
|
||||
|
||||
private static Point GetNearestNeighborSource(ConnectorInfo source, Point endPoint, Rect rectSource, Rect rectSink, out bool flag, bool isInnerPoint)
|
||||
{
|
||||
Point n1, n2; // neighbors
|
||||
GetNeighborCorners(source.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 Point GetNearestNeighborSource(ConnectorInfo source, Point endPoint, Rect rectSource, out bool flag, bool isInnerPoint)
|
||||
{
|
||||
Point n1, n2; // neighbors
|
||||
GetNeighborCorners(source.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 Point GetNearestVisibleNeighborSink(Point currentPoint, Point endPoint, ConnectorInfo sink, Rect rectSource, Rect rectSink)
|
||||
{
|
||||
Point s1, s2; // neighbors on sink side
|
||||
GetNeighborCorners(sink.Orientation, rectSink, out s1, out s2);
|
||||
|
||||
bool flag1 = IsPointVisible(currentPoint, s1, new Rect[] { rectSource, rectSink });
|
||||
bool flag2 = IsPointVisible(currentPoint, s2, new Rect[] { 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 Point(double.NaN, double.NaN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsPointVisible(Point fromPoint, Point targetPoint, Rect[] rectangles)
|
||||
{
|
||||
foreach (Rect rect in rectangles)
|
||||
{
|
||||
if (RectangleIntersectsLine(rect, fromPoint, targetPoint))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsRectVisible(Point fromPoint, Rect targetRect, Rect[] 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(Rect rect, Point startPoint, Point endPoint)
|
||||
{
|
||||
rect.Inflate(-1, -1);
|
||||
return rect.IntersectsWith(new Rect(startPoint, endPoint));
|
||||
}
|
||||
|
||||
private static void GetOppositeCorners(ConnectorOrientation orientation, Rect rect, out Point n1, out Point 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, Rect rect, out Point n1, out Point 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(Point p1, Point p2)
|
||||
{
|
||||
return Point.Subtract(p1, p2).Length;
|
||||
}
|
||||
|
||||
private static Rect GetRectWithMargin(ConnectorInfo connectorThumb, double margin)
|
||||
{
|
||||
Rect rect = new Rect(connectorThumb.DesignerItemLeft,
|
||||
connectorThumb.DesignerItemTop,
|
||||
0,
|
||||
0);
|
||||
|
||||
rect.Inflate(margin, margin);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
private static Point GetOffsetPoint(ConnectorInfo connector, Rect rect, bool isInnerPoint = false)
|
||||
{
|
||||
Point offsetPoint = new Point();
|
||||
if (isInnerPoint)
|
||||
{
|
||||
offsetPoint = new Point(connector.Position.X, connector.Position.Y);
|
||||
return offsetPoint;
|
||||
}
|
||||
|
||||
switch (connector.Orientation)
|
||||
{
|
||||
case ConnectorOrientation.Left:
|
||||
offsetPoint = new Point(rect.Left, connector.Position.Y);
|
||||
break;
|
||||
case ConnectorOrientation.Top:
|
||||
offsetPoint = new Point(connector.Position.X, rect.Top);
|
||||
break;
|
||||
case ConnectorOrientation.Right:
|
||||
offsetPoint = new Point(rect.Right, connector.Position.Y);
|
||||
break;
|
||||
case ConnectorOrientation.Bottom:
|
||||
offsetPoint = new Point(connector.Position.X, rect.Bottom);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return offsetPoint;
|
||||
}
|
||||
|
||||
private static void CheckPathEnd(ConnectorInfo source, ConnectorInfo sink, bool showLastLine, List<Point> linePoints, bool sourceInnerPoint)
|
||||
{
|
||||
if (showLastLine)
|
||||
{
|
||||
Point startPoint = new Point(0, 0);
|
||||
Point endPoint = new Point(0, 0);
|
||||
double marginPath = 15;
|
||||
switch (source.Orientation)
|
||||
{
|
||||
case ConnectorOrientation.Left:
|
||||
startPoint = new Point(source.Position.X - marginPath, source.Position.Y);
|
||||
break;
|
||||
case ConnectorOrientation.Top:
|
||||
startPoint = new Point(source.Position.X, source.Position.Y - marginPath);
|
||||
break;
|
||||
case ConnectorOrientation.Right:
|
||||
startPoint = new Point(source.Position.X + marginPath, source.Position.Y);
|
||||
break;
|
||||
case ConnectorOrientation.Bottom:
|
||||
startPoint = new Point(source.Position.X, source.Position.Y + marginPath);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (sourceInnerPoint)
|
||||
{
|
||||
startPoint = new Point(source.Position.X, source.Position.Y);
|
||||
}
|
||||
|
||||
switch (sink.Orientation)
|
||||
{
|
||||
case ConnectorOrientation.Left:
|
||||
endPoint = new Point(sink.Position.X - marginPath, sink.Position.Y);
|
||||
break;
|
||||
case ConnectorOrientation.Top:
|
||||
endPoint = new Point(sink.Position.X, sink.Position.Y - marginPath);
|
||||
break;
|
||||
case ConnectorOrientation.Right:
|
||||
endPoint = new Point(sink.Position.X + marginPath, sink.Position.Y);
|
||||
break;
|
||||
case ConnectorOrientation.Bottom:
|
||||
endPoint = new Point(sink.Position.X, sink.Position.Y + marginPath);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
linePoints.Insert(0, startPoint);
|
||||
linePoints.Add(endPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
linePoints.Insert(0, source.Position);
|
||||
linePoints.Add(sink.Position);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using AIStudio.Wpf.DiagramDesigner.Geometry;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public class PathGeneratorResult
|
||||
{
|
||||
public PathGeneratorResult(string[] paths, double? sourceMarkerAngle = null, PointBase? sourceMarkerPosition = null,
|
||||
double? targetMarkerAngle = null, PointBase? targetMarkerPosition = null)
|
||||
{
|
||||
Paths = paths;
|
||||
SourceMarkerAngle = sourceMarkerAngle;
|
||||
SourceMarkerPosition = sourceMarkerPosition;
|
||||
TargetMarkerAngle = targetMarkerAngle;
|
||||
TargetMarkerPosition = targetMarkerPosition;
|
||||
}
|
||||
|
||||
public string[] Paths { get; }
|
||||
public double? SourceMarkerAngle { get; }
|
||||
public PointBase? SourceMarkerPosition { get; }
|
||||
public double? TargetMarkerAngle { get; }
|
||||
public PointBase? TargetMarkerPosition { get; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using AIStudio.Wpf.DiagramDesigner.Geometry;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public static partial class PathGenerators
|
||||
{
|
||||
public static PathGeneratorResult Straight(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route, PointBase source, PointBase target)
|
||||
{
|
||||
route = ConcatRouteAndSourceAndTarget(route, source, target);
|
||||
double? sourceAngle = null;
|
||||
double? targetAngle = null;
|
||||
|
||||
sourceAngle = SourceMarkerAdjustement(route, (double)link.ColorViewModel.LeftArrowSizeStyle);
|
||||
targetAngle = TargetMarkerAdjustement(route, (double)link.ColorViewModel.RightArrowPathStyle);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using AIStudio.Wpf.DiagramDesigner.Geometry;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public static partial class PathGenerators
|
||||
{
|
||||
public static double SourceMarkerAdjustement(PointBase[] route, double markerWidth)
|
||||
{
|
||||
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 yChange = markerWidth * Math.Sin(angleInRadians);
|
||||
route[0] = new PointBase(route[0].X - xChange, route[0].Y - yChange);
|
||||
return angleInRadians * 180 / Math.PI;
|
||||
}
|
||||
|
||||
public static double TargetMarkerAdjustement(PointBase[] route, double markerWidth)
|
||||
{
|
||||
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 yChange = markerWidth * Math.Sin(angleInRadians);
|
||||
route[route.Length - 1] = new PointBase(route[route.Length - 1].X - xChange, route[route.Length - 1].Y - yChange);
|
||||
return angleInRadians * 180 / Math.PI;
|
||||
}
|
||||
|
||||
public static PointBase[] ConcatRouteAndSourceAndTarget(PointBase[] route, PointBase source, PointBase target)
|
||||
{
|
||||
var result = new PointBase[route.Length + 2];
|
||||
result[0] = source;
|
||||
route.CopyTo(result, 1);
|
||||
result[route.Length - 1] = target;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace AIStudio.Wpf.DiagramDesigner
|
||||
{
|
||||
public class StraightLinePathFinder : IPathFinder
|
||||
{
|
||||
|
||||
|
||||
public List<PointInfoBase> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, Point sourceA, Point sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
|
||||
{
|
||||
var area = new Rect(sourceA, sourceB);
|
||||
var connectionPoints = PointInfoBase.ToList(new List<Point>()
|
||||
{
|
||||
|
||||
new Point(sourceA.X < sourceB.X ? 0d : area.Width, sourceA.Y < sourceB.Y ? 0d : area.Height ),
|
||||
new Point(sourceA.X > sourceB.X ? 0d : area.Width, sourceA.Y > sourceB.Y ? 0d : area.Height)
|
||||
});
|
||||
|
||||
return connectionPoints;
|
||||
}
|
||||
|
||||
public List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<Point> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, Point sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user