画线优化基本完成

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

@@ -25,7 +25,7 @@ namespace AIStudio.Wpf.Flowchart
{
FlowchartService.InitData(DiagramViewModel.Items.OfType<FlowNode>().ToList(), DiagramViewModel.Items.OfType<ConnectorViewModel>().ToList(), DiagramViewModel);
}
_service.DrawModeViewModel.LineDrawMode = DrawMode.BoundaryConnectingLine;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
}
protected override void InitDiagramViewModel()
@@ -36,7 +36,7 @@ namespace AIStudio.Wpf.Flowchart
DiagramViewModel.GridCellSize = new Size(100, 100);
DiagramViewModel.CellHorizontalAlignment = CellHorizontalAlignment.Center;
DiagramViewModel.CellVerticalAlignment = CellVerticalAlignment.Center;
_service.DrawModeViewModel.LineDrawMode = DrawMode.BoundaryConnectingLine;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
}
protected override void Init()

View File

@@ -17,7 +17,7 @@ namespace AIStudio.Wpf.Logical
}
public LogicalViewModel(string filename, DiagramDocument diagramDocument) : base(filename, diagramDocument)
{
_service.DrawModeViewModel.LineDrawMode = DrawMode.CornerConnectingLine;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
}
protected override void InitDiagramViewModel()
@@ -31,7 +31,7 @@ namespace AIStudio.Wpf.Logical
DiagramViewModel.CellVerticalAlignment = CellVerticalAlignment.None;
DiagramViewModel.Items.CollectionChanged += Items_CollectionChanged;
_service.DrawModeViewModel.LineDrawMode = DrawMode.CornerConnectingLine;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineSmooth;
}
protected override void Init()

View File

@@ -32,7 +32,7 @@ namespace AIStudio.Wpf.Flowchart
readDataTimer.Interval = 1000;
readDataTimer.AutoReset = false;
readDataTimer.Start();
_service.DrawModeViewModel.LineDrawMode = DrawMode.BoundaryConnectingLine;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineBoundary;
}
protected override void InitDiagramViewModel()
@@ -43,7 +43,7 @@ namespace AIStudio.Wpf.Flowchart
DiagramViewModel.GridCellSize = new Size(100, 60);
DiagramViewModel.CellHorizontalAlignment = CellHorizontalAlignment.Center;
DiagramViewModel.CellVerticalAlignment = CellVerticalAlignment.Center;
_service.DrawModeViewModel.LineDrawMode = DrawMode.BoundaryConnectingLine;
_service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineBoundary;
}
private System.Timers.Timer readDataTimer = new System.Timers.Timer();

View File

@@ -802,10 +802,10 @@
</Fluent:ToggleButton>
<Fluent:SplitButton Header="连接线" GroupName="DrawMode" IsCheckable="True" IsChecked="{Binding LineDrawModeSelected}" Icon="{iconPacks:Material Kind=VectorPolyline}" Width="50" VerticalAlignment="Top">
<Fluent:MenuItem Header="曲线连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='SmoothConnectingLine'}, ConverterParameter='SmoothConnectingLine'}" Icon="{iconPacks:Material Kind=VectorRadius}"/>
<Fluent:MenuItem Header="直线连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='StraightConnectingLine'}, ConverterParameter='StraightConnectingLine'}" Icon="{iconPacks:Material Kind=VectorLine}"/>
<Fluent:MenuItem Header="折线连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='CornerConnectingLine'}, ConverterParameter='CornerConnectingLine'}" Icon="{iconPacks:Material Kind=VectorPolyline}"/>
<Fluent:MenuItem Header="边界连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='BoundaryConnectingLine'}, ConverterParameter='BoundaryConnectingLine'}" Icon="{iconPacks:Material Kind=VectorPolylineEdit}"/>
<Fluent:MenuItem Header="曲线连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='ConnectingLineSmooth'}, ConverterParameter='ConnectingLineSmooth'}" Icon="{iconPacks:Material Kind=VectorRadius}"/>
<Fluent:MenuItem Header="直线连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='ConnectingLineStraight'}, ConverterParameter='ConnectingLineStraight'}" Icon="{iconPacks:Material Kind=VectorLine}"/>
<Fluent:MenuItem Header="折线连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='ConnectingLineCorner'}, ConverterParameter='ConnectingLineCorner'}" Icon="{iconPacks:Material Kind=VectorPolyline}"/>
<Fluent:MenuItem Header="边界连接线" Size="Middle" IsCheckable="True" IsChecked="{Binding LineDrawMode,Converter={dd:ConverterValueMapToBool Parameter='ConnectingLineBoundary'}, ConverterParameter='ConnectingLineBoundary'}" Icon="{iconPacks:Material Kind=VectorPolylineEdit}"/>
<Fluent:SplitButton.Style>
<Style TargetType="{x:Type Fluent:SplitButton}" BasedOn="{StaticResource RibbonSplitButtonStyle}">
<Setter Property="LargeIcon">
@@ -814,28 +814,28 @@
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding LineDrawMode}" Value="SmoothConnectingLine">
<DataTrigger Binding="{Binding LineDrawMode}" Value="ConnectingLineSmooth">
<Setter Property="LargeIcon">
<Setter.Value>
<iconPacks:PackIconMaterial Kind="VectorRadius" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding LineDrawMode}" Value="StraightConnectingLine">
<DataTrigger Binding="{Binding LineDrawMode}" Value="ConnectingLineStraight">
<Setter Property="LargeIcon">
<Setter.Value>
<iconPacks:PackIconMaterial Kind="VectorLine" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding LineDrawMode}" Value="CornerConnectingLine">
<DataTrigger Binding="{Binding LineDrawMode}" Value="ConnectingLineCorner">
<Setter Property="LargeIcon">
<Setter.Value>
<iconPacks:PackIconMaterial Kind="VectorPolyline" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding LineDrawMode}" Value="BoundaryConnectingLine">
<DataTrigger Binding="{Binding LineDrawMode}" Value="ConnectingLineBoundary">
<Setter Property="LargeIcon">
<Setter.Value>
<iconPacks:PackIconMaterial Kind="VectorPolylineEdit" VerticalAlignment="Center" HorizontalAlignment="Center"/>
@@ -852,9 +852,9 @@
</Fluent:SplitButton.ToolTip>
</Fluent:SplitButton>
<Fluent:SplitButton Header="连接方式" GroupName="RouterMode" IsCheckable="False" IsChecked="{Binding LineRouterModeSelected}" Icon="{iconPacks:FontAwesome Kind=WindowMinimizeRegular}" Width="50" VerticalAlignment="Top">
<Fluent:MenuItem Header="普通" Size="Middle" IsCheckable="True" IsChecked="{Binding LineRouterMode,Converter={dd:ConverterValueMapToBool Parameter='Normal'}, ConverterParameter='Normal'}" Icon="{iconPacks:FontAwesome Kind=WindowMinimizeRegular}"/>
<Fluent:MenuItem Header="正交" Size="Middle" IsCheckable="True" IsChecked="{Binding LineRouterMode,Converter={dd:ConverterValueMapToBool Parameter='Orthogonal'}, ConverterParameter='Orthogonal'}" Icon="{iconPacks:FontAwesome Kind=BorderStyleSolid}"/>
<!--<Fluent:SplitButton Header="连接方式" GroupName="RouterMode" IsCheckable="False" IsChecked="{Binding LineRouterModeSelected}" Icon="{iconPacks:FontAwesome Kind=WindowMinimizeRegular}" Width="50" VerticalAlignment="Top">
<Fluent:MenuItem Header="普通" Size="Middle" IsCheckable="True" IsChecked="{Binding LineRouterMode,Converter={dd:ConverterValueMapToBool Parameter='RouterNormal'}, ConverterParameter='RouterNormal'}" Icon="{iconPacks:FontAwesome Kind=WindowMinimizeRegular}"/>
<Fluent:MenuItem Header="正交" Size="Middle" IsCheckable="True" IsChecked="{Binding LineRouterMode,Converter={dd:ConverterValueMapToBool Parameter='RouterOrthogonal'}, ConverterParameter='RouterOrthogonal'}" Icon="{iconPacks:FontAwesome Kind=BorderStyleSolid}"/>
<Fluent:SplitButton.Style>
<Style TargetType="{x:Type Fluent:SplitButton}" BasedOn="{StaticResource RibbonSplitButtonStyle}">
<Setter Property="LargeIcon">
@@ -863,14 +863,14 @@
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding LineRouterMode}" Value="Normal">
<DataTrigger Binding="{Binding LineRouterMode}" Value="RouterNormal">
<Setter Property="LargeIcon">
<Setter.Value>
<iconPacks:PackIconFontAwesome Kind="WindowMinimizeRegular" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding LineRouterMode}" Value="Orthogonal">
<DataTrigger Binding="{Binding LineRouterMode}" Value="RouterOrthogonal">
<Setter Property="LargeIcon">
<Setter.Value>
<iconPacks:PackIconFontAwesome Kind="BorderStyleSolid" VerticalAlignment="Center" HorizontalAlignment="Center"/>
@@ -885,7 +885,7 @@
Text="连接线的连接方式"
Width="190" />
</Fluent:SplitButton.ToolTip>
</Fluent:SplitButton>
</Fluent:SplitButton>-->
<Fluent:SplitButton Header="形状" GroupName="DrawMode" IsCheckable="True" IsChecked="{Binding ShapeDrawModeSelected}" Width="50" VerticalAlignment="Top">
<Fluent:MenuItem Header="矩形工具" Size="Middle" IsCheckable="True" IsChecked="{Binding ShapeDrawMode,Converter={dd:ConverterValueMapToBool Parameter='Rectangle'}, ConverterParameter='Rectangle'}" Icon="{iconPacks:Material Kind=RectangleOutline}" />

View File

@@ -75,7 +75,7 @@ namespace AIStudio.Wpf.DiagramDesigner.Test.ViewModels
DiagramViewModel.CellVerticalAlignment = CellVerticalAlignment.Center;
DiagramViewModel.PageSizeType = PageSizeType.Custom;
DiagramViewModel.PageSize = new Size(double.NaN, double.NaN);
DiagramViewModel.DrawModeViewModel = new DrawModeViewModel() { LineDrawMode = DrawMode.BoundaryConnectingLine };
DiagramViewModel.DrawModeViewModel = new DrawModeViewModel() { LineDrawMode = DrawMode.ConnectingLineBoundary };
DiagramViewModel.PropertyChanged += DiagramViewModel_PropertyChanged;
}

View File

@@ -284,7 +284,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
e.Handled = true;
if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.SmoothConnectingLine)
if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.ConnectingLineSmooth)
{
if (connectorsHit.Count == 0)
{
@@ -378,7 +378,7 @@ namespace AIStudio.Wpf.DiagramDesigner
sinkDataItem.DataItem.Parent.Items[indexOfLastTempConnection]);
sinkDataItem.DataItem.Parent.AddItemCommand.Execute(new ConnectorViewModel(_viewModel, sourceDataItem, sinkDataItem, DrawMode, RouterMode));
}
else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.SmoothConnectingLine && connectorsHit.Count() == 1)
else if (_service.DrawModeViewModel.GetDrawMode() == DrawMode.DirectLine && connectorsHit.Count() == 1)
{
LinkPointDesignerItemViewModel pointItemView = new LinkPointDesignerItemViewModel(e.GetPosition(this));
FullyCreatedConnectorInfo sinkDataItem = pointItemView.TopConnector;

View File

@@ -13,10 +13,10 @@ namespace AIStudio.Wpf.DiagramDesigner
Polyline = 4,
Polygon = 5,
DirectLine = 6,
SmoothConnectingLine = 10,
StraightConnectingLine = 11,
CornerConnectingLine = 12,
BoundaryConnectingLine = 13,
ConnectingLineSmooth = 10,
ConnectingLineStraight = 11,
ConnectingLineCorner = 12,
ConnectingLineBoundary = 13,
Text = 20,
}
}

View File

@@ -6,7 +6,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
public enum RouterMode
{
Normal,
Orthogonal
RouterNormal,
RouterOrthogonal
}
}

View File

@@ -1,179 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class BoundaryPathFinder : IPathFinder
{
public List<ConnectorPoint> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, PointBase sourceA, PointBase sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
List<ConnectorPoint> connectionPoints;
var isFullConnection = sinkConnectorInfo is FullyCreatedConnectorInfo;
var points = new List<PointBase>()
{
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 = ConnectorPoint.ToList(GetConnectionLine(diagramViewModel, sourceInfo, sinkInfo, false, sourceConnectorInfo.IsInnerPoint));
//EndPoint = ConnectionPoints.Last();
}
else
{
connectionPoints = ConnectorPoint.ToList(GetConnectionLine(diagramViewModel, sourceInfo, points[1], sourceConnectorInfo.Orientation, false, sourceConnectorInfo.IsInnerPoint));
//EndPoint = new PointBase();
}
return connectionPoints;
}
public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, PointBase position)
{
return new ConnectorInfo()
{
Orientation = orientation,
DesignerItemSize = new SizeBase(width, height),
DesignerItemLeft = left,
DesignerItemTop = top,
Position = position
};
}
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
{
var points = new List<PointBase>();
var ends = new List<PointBase> { 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<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, PointBase sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
{
var points = new List<PointBase>();
var ends = new List<PointBase> { 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<PointBase> GetMiddlePoints(ConnectorInfo source, ConnectorInfo sink, SizeBase gridCellSize, double gridMargin, bool isFullConnection)
{
var points = new List<PointBase>();
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 PointBase(GetNearestCross(p0.X, p1.X), GetNearestCross(p0.Y, p1.Y));
var p3 = new PointBase(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 PointBase(p2.X, p3.Y));
points.Add(p3);
points.Add(p1);
}
DoScale(points, gridCellSize, gridMargin);
}
return points;
}
private PointBase GetFirstSegment(ConnectorOrientation orientation, PointBase point, SizeBase 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 PointBase(x, y - 0.5);
else if (orientation == ConnectorOrientation.Bottom)
return new PointBase(x, y + 0.5);
else if (orientation == ConnectorOrientation.Left)
return new PointBase(x - 0.5, y);
else
return new PointBase(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 PointBase SegmentMiddlePoint(PointBase p1, PointBase p2)
{
return new PointBase((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
}
private void DoScale(List<PointBase> points, SizeBase cellSize, double margin)
{
for (int i = 0; i < points.Count; i++)
{
points[i] = new PointBase(points[i].X * cellSize.Width + margin,
points[i].Y * cellSize.Height + margin);
}
}
private void DoShift(PointBase[] points)
{
double left = new PointBase[] { points.FirstOrDefault(), points.LastOrDefault() }.Min(p => p.X);
double top = new PointBase[] { 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;
}
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public interface IPathFinder
{
List<ConnectorPoint> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, PointBase sourceA, PointBase sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo);
List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false);
List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, PointBase sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false);
}
}

View File

@@ -1,35 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class StraightLinePathFinder : IPathFinder
{
public List<ConnectorPoint> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, PointBase sourceA, PointBase sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
{
var area = new RectangleBase(sourceA, sourceB);
var connectionPoints = ConnectorPoint.ToList(new List<PointBase>()
{
new PointBase(sourceA.X < sourceB.X ? 0d : area.Width, sourceA.Y < sourceB.Y ? 0d : area.Height ),
new PointBase(sourceA.X > sourceB.X ? 0d : area.Width, sourceA.Y > sourceB.Y ? 0d : area.Height)
});
return connectionPoints;
}
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
{
throw new NotImplementedException();
}
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, PointBase sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
{
throw new NotImplementedException();
}
}
}

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

@@ -1,85 +1,59 @@
using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Text;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
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
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;
public List<ConnectorPoint> UpdateConnectionPoints(IDiagramViewModel diagramViewModel, PointBase sourceA, PointBase sourceB, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
private static PointBase[] GetRouteWithFullConnectionLine(IDiagramViewModel _, ConnectorViewModel link, PointBase[] route)
{
List<ConnectorPoint> connectionPoints;
var isFullConnection = sinkConnectorInfo is FullyCreatedConnectorInfo;
var area = new RectangleBase(sourceA, sourceB);
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;
var points = new List<PointBase>()
{
new PointBase(sourceA.X < sourceB.X ? 0d : area.Width, sourceA.Y < sourceB.Y ? 0d : area.Height ),
new PointBase(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 = ConnectorPoint.ToList(GetConnectionLine(diagramViewModel, sourceInfo, sinkInfo, false, sourceConnectorInfo.IsInnerPoint));
//EndPoint = ConnectionPoints.Last();
}
else
{
connectionPoints = ConnectorPoint.ToList(GetConnectionLine(diagramViewModel, sourceInfo, points[1], sourceConnectorInfo.Orientation, false, sourceConnectorInfo.IsInnerPoint));
//EndPoint = new PointBase();
}
return connectionPoints;
}
public ConnectorInfo ConnectorInfo(ConnectorOrientation orientation, double left, double top, double width, double height, PointBase position)
{
return new ConnectorInfo()
{
Orientation = orientation,
DesignerItemSize = new SizeBase(width, height),
DesignerItemLeft = left,
DesignerItemTop = top,
Position = position
};
}
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, ConnectorInfo sink, bool showLastLine, bool sourceInnerPoint = false)
{
List<PointBase> linePoints = new List<PointBase>();
int margin1 = sourceInnerPoint ? 0 : const_margin;
int margin2 = const_margin;
RectangleBase rectSource = GetRectWithMargin(source, margin1);
RectangleBase rectSink = GetRectWithMargin(sink, margin2);
RectangleBase rectSource = GetRectWithMargin(sourcePoint, margin1);
RectangleBase rectSink = GetRectWithMargin(sinkPoint, margin2);
PointBase startPoint = GetOffsetPoint(source, rectSource, sourceInnerPoint);
PointBase endPoint = GetOffsetPoint(sink, rectSink);
PointBase startPoint = GetOffsetPoint(sourcePoint, sourceOrientation, rectSource, sourceInnerPoint);
PointBase endPoint = GetOffsetPoint(sinkPoint, sinkOrientation, rectSink);
linePoints.Add(startPoint);
PointBase currentPoint = startPoint;
@@ -97,7 +71,7 @@ namespace AIStudio.Wpf.DiagramDesigner
break;
}
PointBase neighbour = GetNearestVisibleNeighborSink(currentPoint, endPoint, sink, rectSource, rectSink);
PointBase neighbour = GetNearestVisibleNeighborSink(currentPoint, endPoint, sinkOrientation, rectSource, rectSink);
if (!double.IsNaN(neighbour.X))
{
linePoints.Add(neighbour);
@@ -109,7 +83,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (currentPoint == startPoint)
{
bool flag;
PointBase n = GetNearestNeighborSource(source, endPoint, rectSource, rectSink, out flag, sourceInnerPoint);
PointBase n = GetNearestNeighborSource(sourceOrientation, endPoint, rectSource, rectSink, out flag, sourceInnerPoint);
if (linePoints.Contains(n))
{
break;
@@ -120,7 +94,7 @@ namespace AIStudio.Wpf.DiagramDesigner
if (!IsRectVisible(currentPoint, rectSink, new RectangleBase[] { rectSource }))
{
PointBase n1, n2;
GetOppositeCorners(source.Orientation, rectSource, out n1, out n2, sourceInnerPoint);
GetOppositeCorners(sourceOrientation, rectSource, out n1, out n2, sourceInnerPoint);
if (flag)
{
linePoints.Add(n1);
@@ -154,8 +128,8 @@ namespace AIStudio.Wpf.DiagramDesigner
{
PointBase n1, n2; // neighbour corner
PointBase s1, s2; // opposite corner
GetNeighborCorners(sink.Orientation, rectSink, out s1, out s2);
GetOppositeCorners(sink.Orientation, rectSink, out n1, out n2);
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 });
@@ -260,20 +234,27 @@ namespace AIStudio.Wpf.DiagramDesigner
linePoints.Add(endPoint);
}
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource, rectSink }, source.Orientation, sink.Orientation);
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource, rectSink }, sourceOrientation, sinkOrientation);
CheckPathEnd(source, sink, showLastLine, linePoints, sourceInnerPoint);
linePoints.Insert(0, sourcePoint);
linePoints.Add(sinkPoint);
return linePoints;
return linePoints.ToArray();
}
public List<PointBase> GetConnectionLine(IDiagramViewModel diagramViewModel, ConnectorInfo source, PointBase sinkPoint, ConnectorOrientation preferredOrientation, bool showLastLine, bool isInnerPoint = false)
private static PointBase[] GetRouteWithPartConnectionLine(IDiagramViewModel diagramViewModel, ConnectorViewModel link, PointBase[] route)
{
List<PointBase> linePoints = new List<PointBase>();
int margin = isInnerPoint ? 0 : const_margin;
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;
RectangleBase rectSource = GetRectWithMargin(source, margin);
PointBase startPoint = GetOffsetPoint(source, rectSource, isInnerPoint);
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);
@@ -290,7 +271,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
bool sideFlag;
PointBase n = GetNearestNeighborSource(source, endPoint, rectSource, out sideFlag, isInnerPoint);
PointBase n = GetNearestNeighborSource(sourceOrientation, endPoint, rectSource, out sideFlag, sourceInnerPoint);
linePoints.Add(n);
currentPoint = n;
@@ -302,7 +283,7 @@ namespace AIStudio.Wpf.DiagramDesigner
else
{
PointBase n1, n2;
GetOppositeCorners(source.Orientation, rectSource, out n1, out n2, isInnerPoint);
GetOppositeCorners(sourceOrientation, rectSource, out n1, out n2, sourceInnerPoint);
if (sideFlag)
linePoints.Add(n1);
else
@@ -319,16 +300,13 @@ namespace AIStudio.Wpf.DiagramDesigner
}
if (preferredOrientation != ConnectorOrientation.None)
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, source.Orientation, preferredOrientation);
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, sourceOrientation, preferredOrientation);
else
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, source.Orientation, GetOpositeOrientation(source.Orientation));
linePoints = OptimizeLinePoints(linePoints, new RectangleBase[] { rectSource }, sourceOrientation, GetOpositeOrientation(sourceOrientation));
linePoints.Insert(0, sourcePoint);
if (!showLastLine)
{
linePoints.Insert(0, source.Position);
}
return linePoints;
return linePoints.ToArray();
}
private static List<PointBase> OptimizeLinePoints(List<PointBase> linePoints, RectangleBase[] rectangles, ConnectorOrientation sourceOrientation, ConnectorOrientation sinkOrientation)
@@ -434,31 +412,10 @@ namespace AIStudio.Wpf.DiagramDesigner
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 PointBase GetNearestNeighborSource(ConnectorInfo source, PointBase endPoint, RectangleBase rectSource, RectangleBase rectSink, out bool flag, bool isInnerPoint)
private static PointBase GetNearestNeighborSource(ConnectorOrientation orientation, PointBase endPoint, RectangleBase rectSource, RectangleBase rectSink, out bool flag, bool isInnerPoint)
{
PointBase n1, n2; // neighbors
GetNeighborCorners(source.Orientation, rectSource, out n1, out n2, isInnerPoint);
GetNeighborCorners(orientation, rectSource, out n1, out n2, isInnerPoint);
if (rectSink.Contains(n1))
{
@@ -484,10 +441,10 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private static PointBase GetNearestNeighborSource(ConnectorInfo source, PointBase endPoint, RectangleBase rectSource, out bool flag, bool isInnerPoint)
private static PointBase GetNearestNeighborSource(ConnectorOrientation orientation, PointBase endPoint, RectangleBase rectSource, out bool flag, bool isInnerPoint)
{
PointBase n1, n2; // neighbors
GetNeighborCorners(source.Orientation, rectSource, out n1, out n2, isInnerPoint);
GetNeighborCorners(orientation, rectSource, out n1, out n2, isInnerPoint);
if ((Distance(n1, endPoint) <= Distance(n2, endPoint)))
{
@@ -501,10 +458,10 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private static PointBase GetNearestVisibleNeighborSink(PointBase currentPoint, PointBase endPoint, ConnectorInfo sink, RectangleBase rectSource, RectangleBase rectSink)
private static PointBase GetNearestVisibleNeighborSink(PointBase currentPoint, PointBase endPoint, ConnectorOrientation orientation, RectangleBase rectSource, RectangleBase rectSink)
{
PointBase s1, s2; // neighbors on sink side
GetNeighborCorners(sink.Orientation, rectSink, out s1, out s2);
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 });
@@ -633,40 +590,36 @@ namespace AIStudio.Wpf.DiagramDesigner
return PointBase.Subtract(p1, p2).Length;
}
private static RectangleBase GetRectWithMargin(ConnectorInfo connectorThumb, double margin)
private static RectangleBase GetRectWithMargin(PointBase point, double margin)
{
RectangleBase rect = new RectangleBase(connectorThumb.DesignerItemLeft,
connectorThumb.DesignerItemTop,
0,
0);
RectangleBase rect = new RectangleBase(point.X, point.Y, 0, 0);
rect.Inflate(margin, margin);
return rect;
}
private static PointBase GetOffsetPoint(ConnectorInfo connector, RectangleBase rect, bool isInnerPoint = false)
private static PointBase GetOffsetPoint(PointBase point, ConnectorOrientation orientation, RectangleBase rect, bool isInnerPoint = false)
{
PointBase offsetPoint = new PointBase();
if (isInnerPoint)
{
offsetPoint = new PointBase(connector.Position.X, connector.Position.Y);
offsetPoint = new PointBase(point.X, point.Y);
return offsetPoint;
}
switch (connector.Orientation)
switch (orientation)
{
case ConnectorOrientation.Left:
offsetPoint = new PointBase(rect.Left, connector.Position.Y);
offsetPoint = new PointBase(rect.Left, point.Y);
break;
case ConnectorOrientation.Top:
offsetPoint = new PointBase(connector.Position.X, rect.Top);
offsetPoint = new PointBase(point.X, rect.Top);
break;
case ConnectorOrientation.Right:
offsetPoint = new PointBase(rect.Right, connector.Position.Y);
offsetPoint = new PointBase(rect.Right, point.Y);
break;
case ConnectorOrientation.Bottom:
offsetPoint = new PointBase(connector.Position.X, rect.Bottom);
offsetPoint = new PointBase(point.X, rect.Bottom);
break;
default:
break;
@@ -675,62 +628,6 @@ namespace AIStudio.Wpf.DiagramDesigner
return offsetPoint;
}
private static void CheckPathEnd(ConnectorInfo source, ConnectorInfo sink, bool showLastLine, List<PointBase> linePoints, bool sourceInnerPoint)
{
if (showLastLine)
{
PointBase startPoint = new PointBase(0, 0);
PointBase endPoint = new PointBase(0, 0);
double marginPath = 15;
switch (source.Orientation)
{
case ConnectorOrientation.Left:
startPoint = new PointBase(source.Position.X - marginPath, source.Position.Y);
break;
case ConnectorOrientation.Top:
startPoint = new PointBase(source.Position.X, source.Position.Y - marginPath);
break;
case ConnectorOrientation.Right:
startPoint = new PointBase(source.Position.X + marginPath, source.Position.Y);
break;
case ConnectorOrientation.Bottom:
startPoint = new PointBase(source.Position.X, source.Position.Y + marginPath);
break;
default:
break;
}
if (sourceInnerPoint)
{
startPoint = new PointBase(source.Position.X, source.Position.Y);
}
switch (sink.Orientation)
{
case ConnectorOrientation.Left:
endPoint = new PointBase(sink.Position.X - marginPath, sink.Position.Y);
break;
case ConnectorOrientation.Top:
endPoint = new PointBase(sink.Position.X, sink.Position.Y - marginPath);
break;
case ConnectorOrientation.Right:
endPoint = new PointBase(sink.Position.X + marginPath, sink.Position.Y);
break;
case ConnectorOrientation.Bottom:
endPoint = new PointBase(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)

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);

View File

@@ -5,7 +5,7 @@ using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class NormalRouter : IRouter
public class RouterNormal : IRouter
{
public PointBase[] Get(IDiagramViewModel _, ConnectorViewModel link)
{

View File

@@ -5,7 +5,7 @@ using AIStudio.Wpf.DiagramDesigner.Geometrys;
namespace AIStudio.Wpf.DiagramDesigner
{
public class OrthogonalRouter : IRouter
public class RouterOrthogonal : IRouter
{
public PointBase[] Get(IDiagramViewModel _, ConnectorViewModel link)
{

View File

@@ -118,7 +118,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private DrawMode _lineDrawMode = DrawMode.CornerConnectingLine;
private DrawMode _lineDrawMode = DrawMode.ConnectingLineSmooth;
public DrawMode LineDrawMode
{
get
@@ -132,7 +132,7 @@ namespace AIStudio.Wpf.DiagramDesigner
}
}
private RouterMode _lineRouterMode = RouterMode.Normal;
private RouterMode _lineRouterMode = RouterMode.RouterNormal;
public RouterMode LineRouterMode
{
get

View File

@@ -14,7 +14,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public ConnectorViewModel(IDiagramViewModel parent, FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode, RouterMode routerMode)
{
Parent = parent;
PathMode = drawMode.ToString().Replace("ConnectingLine","");
PathMode = drawMode.ToString();
RouterMode = routerMode.ToString();
Init(sourceConnectorInfo, sinkConnectorInfo);
}
@@ -26,9 +26,9 @@ namespace AIStudio.Wpf.DiagramDesigner
Init(sourceConnectorInfo, sinkConnectorInfo);
}
public ConnectorViewModel(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode, RouterMode routerMode) :this(null, sourceConnectorInfo, sinkConnectorInfo, drawMode, routerMode)
public ConnectorViewModel(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo, DrawMode drawMode, RouterMode routerMode) : this(null, sourceConnectorInfo, sinkConnectorInfo, drawMode, routerMode)
{
}
private void Init(FullyCreatedConnectorInfo sourceConnectorInfo, ConnectorInfoBase sinkConnectorInfo)
@@ -36,10 +36,10 @@ namespace AIStudio.Wpf.DiagramDesigner
this.Parent = sourceConnectorInfo.DataItem.Parent;
var routetype = GlobalType.AllTypes.Where(p => typeof(IRouter).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == RouterMode);
Router = routetype != null ? (System.Activator.CreateInstance(routetype) as IRouter) : new NormalRouter();
Router = routetype != null ? (System.Activator.CreateInstance(routetype) as IRouter) : new RouterNormal();
var pathGeneratortype = GlobalType.AllTypes.Where(p => typeof(IPathGenerator).IsAssignableFrom(p)).FirstOrDefault(p => p.Name == PathMode);
PathGenerator = pathGeneratortype != null ? (System.Activator.CreateInstance(pathGeneratortype) as IPathGenerator) : new SmoothPathGenerator();
PathGenerator = pathGeneratortype != null ? (System.Activator.CreateInstance(pathGeneratortype) as IPathGenerator) : new ConnectingLineSmooth();
this.SourceConnectorInfo = sourceConnectorInfo;
this.SinkConnectorInfo = sinkConnectorInfo;
@@ -72,7 +72,7 @@ namespace AIStudio.Wpf.DiagramDesigner
public override Type ToXmlType()
{
return typeof(ConnectionItem);
}
}
private PointBase _sourceA;
public PointBase SourceA
@@ -249,7 +249,7 @@ namespace AIStudio.Wpf.DiagramDesigner
{
SourceB = _sinkConnectorInfo.Location;
if (_sinkConnectorInfo is FullyCreatedConnectorInfo)
{
{
(((FullyCreatedConnectorInfo)_sinkConnectorInfo).DataItem as INotifyPropertyChanged).PropertyChanged += new WeakINPCEventHandler(ConnectorViewModel_PropertyChanged).Handler;
}
}
@@ -297,18 +297,19 @@ namespace AIStudio.Wpf.DiagramDesigner
private void UpdateConnectionPoints()
{
//ConnectionPoints = PathFinder.UpdateConnectionPoints(Parent, SourceA, SourceB, SourceConnectorInfo, SinkConnectorInfo);
//StartPoint = ConnectionPoints.First();
//EndPoint = ConnectionPoints.Last();
if (SourceConnectorInfo == null || SinkConnectorInfo == null)
return;
var route = Router.Get(Parent, this);
(var source, var target) = FindConnectionPoints(route);
if (source == null || target == null)
return;
PathGeneratorResult = PathGenerator.Get(Parent, this, route, source.Value, target.Value);
}
StartPoint = PathGeneratorResult.SourceMarkerPosition ?? new PointBase();
EndPoint = PathGeneratorResult.TargetMarkerPosition ?? new PointBase();
}
private void ConnectorViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
@@ -338,7 +339,7 @@ namespace AIStudio.Wpf.DiagramDesigner
break;
}
}
}
public SimpleCommand DeleteConnectionCommand
{
@@ -369,14 +370,14 @@ namespace AIStudio.Wpf.DiagramDesigner
TextDesignerItemViewModel textitem = new TextDesignerItemViewModel();
textitem.ItemWidth = Double.NaN;
textitem.ItemHeight = double.NaN;
if (diagramVM.DiagramType == DiagramType.FlowChart)
{
var mid = (int)(ConnectionPoints.Count / 2);
var p = BoundaryPathFinder.SegmentMiddlePoint(ConnectionPoints[mid - 1], ConnectionPoints[mid]);
textitem.Left = this.Area.Left + p.X + 2;
textitem.Top = this.Area.Top + p.Y - 15;
}
else
//if (this.PathMode == DrawMode.ConnectingLineBoundary.ToString())
//{
// var mid = (int)(ConnectionPoints.Count / 2);
// var p = PathGenerators.SegmentMiddlePoint(ConnectionPoints[mid - 1], ConnectionPoints[mid]);
// textitem.Left = this.Area.Left + p.X + 2;
// textitem.Top = this.Area.Top + p.Y - 15;
//}
//else
{
textitem.Left = this.Area.Left + this.Area.Width / 2 - 16;
textitem.Top = this.Area.Top + this.Area.Height / 2 - 5;

View File

@@ -225,7 +225,7 @@ namespace AIStudio.Wpf.Flowchart.Models
{
FullyCreatedConnectorInfo sourceConnectorInfo = sourceNode.Connectors.FirstOrDefault(p => p.Orientation.ToString() == diagramLink.SourcePortAlignment);
FullyCreatedConnectorInfo sinkConnectorInfo = targetNode.Connectors.FirstOrDefault(p => p.Orientation.ToString() == diagramLink.TargetPortAlignment);
ConnectorViewModel linkModel = new ConnectorViewModel(diagram, sourceConnectorInfo, sinkConnectorInfo, diagram.DrawModeViewModel?.LineDrawMode ?? DrawMode.SmoothConnectingLine, diagram.DrawModeViewModel?.LineRouterMode ?? RouterMode.Normal);
ConnectorViewModel linkModel = new ConnectorViewModel(diagram, sourceConnectorInfo, sinkConnectorInfo, diagram.DrawModeViewModel?.LineDrawMode ?? DrawMode.ConnectingLineSmooth, diagram.DrawModeViewModel?.LineRouterMode ?? RouterMode.RouterNormal);
linkModel.Id = new Guid(diagramLink.Id);
linkModel.ColorViewModel.LineColor.Color = SerializeHelper.DeserializeColor(diagramLink.Color);
linkModel.ColorViewModel.LineWidth = diagramLink.Width;