+ Added selective vertex and edge support to METRO version [METRO]

+ Added selective vertex and edge support for following algorithms: Circular [ALL]
+ Fixed layout algorithm calculations to always receive actual vertex positions as input parameter
 This will fix selective VaE support for default algorithms. [WPF, METRO]
This commit is contained in:
Alexander Smirnov 2015-05-13 01:27:57 +03:00
Родитель 0fd3ea83ac
Коммит ef4e8498cb
15 изменённых файлов: 119 добавлений и 58 удалений

Просмотреть файл

@ -8,5 +8,5 @@ using System.Reflection;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("2.1.8.0")]
[assembly: AssemblyFileVersion("2.1.8.0")]
[assembly: AssemblyVersion("2.1.9.0")]
[assembly: AssemblyFileVersion("2.1.9.0")]

Просмотреть файл

@ -1,4 +1,13 @@
RELEASE 2.1.8
RELEASE 2.1.9
+ Added selective vertex and edge support to METRO version [METRO]
+ Added selective vertex and edge support for following algorithms: Circular [ALL]
+ Fixed layout algorithm calculations to always receive actual vertex positions as input parameter
This will fix selective VaE support for default algorithms. [WPF, METRO]
!BREAKING CHANGES
RELEASE 2.1.8
+ Added basic support for Image based edge pointers. Introduced new object for EdgeControl template: [WPF, METRO(bugged)]
1. EdgePointerImage class with name "PART_EdgePointerImageForSource" - marks edge source pointer (new!)
2. EdgePointerImage class with name "PART_EdgePointerImageForTarget" - marks edge target pointer

Просмотреть файл

@ -27,6 +27,7 @@
<mui:LinkGroup.Links>
<mui:Link DisplayName="General" Source="/Pages/ThemedGraph.xaml" />
<mui:Link DisplayName="Editor" Source="/Pages/EditorGraph.xaml" />
<!--<mui:Link DisplayName="Neural Network" Source="/Pages/NNGraph.xaml" />-->
</mui:LinkGroup.Links>
</mui:LinkGroup>
<mui:LinkGroup DisplayName="Edge routing">

Просмотреть файл

@ -32,6 +32,7 @@
<DockPanel Grid.Row="1" Grid.Column="1">
<Button DockPanel.Dock="Top" Name="butRun">Run</Button>
<Button DockPanel.Dock="Top" Name="butRelay">Relay</Button>
<Button DockPanel.Dock="Top" Name="butTest">Test</Button>
</DockPanel>

Просмотреть файл

@ -1,10 +1,13 @@
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using GraphX;
using GraphX.GraphSharp.Algorithms.OverlapRemoval;
using GraphX.Models;
using GraphX.PCL.Common.Enums;
using ShowcaseApp.WPF.Models;
using Point = GraphX.Measure.Point;
namespace ShowcaseApp.WPF.Pages
{
@ -19,6 +22,12 @@ namespace ShowcaseApp.WPF.Pages
DataContext = this;
butRun.Click += butRun_Click;
butTest.Click += butTest_Click;
butRelay.Click +=ButRelayOnClick;
}
private void ButRelayOnClick(object sender, RoutedEventArgs routedEventArgs)
{
dg_Area.RelayoutGraph(true);
}
void butTest_Click(object sender, RoutedEventArgs e)
@ -40,8 +49,12 @@ namespace ShowcaseApp.WPF.Pages
dg_Area.GenerateGraph(true);*/
var logicCore = new LogicCoreExample() { Graph = ShowcaseHelper.GenerateDataGraph(25) };
foreach (var item in logicCore.Graph.Vertices.Take(4))
{
item.SkipProcessing = ProcessingOptionEnum.Freeze;
}
logicCore.DefaultLayoutAlgorithm = LayoutAlgorithmTypeEnum.ISOM;
logicCore.DefaultLayoutAlgorithm = LayoutAlgorithmTypeEnum.Circular;
logicCore.DefaultOverlapRemovalAlgorithm = OverlapRemovalAlgorithmTypeEnum.FSA;
logicCore.DefaultOverlapRemovalAlgorithmParams = logicCore.AlgorithmFactory.CreateOverlapRemovalParameters(GraphX.OverlapRemovalAlgorithmTypeEnum.FSA);
((OverlapRemovalParameters)logicCore.DefaultOverlapRemovalAlgorithmParams).HorizontalGap = 50;
@ -59,6 +72,11 @@ namespace ShowcaseApp.WPF.Pages
//dg_Area.InvalidateVisual();
dg_Area.GenerateGraph(true);
foreach (var item in logicCore.Graph.Vertices.Take(4))
{
dg_Area.VertexList[item].SetPosition(new System.Windows.Point());
}
//dg_Area.RelayoutGraph();
//dg_zoomctrl.ZoomToFill();

Просмотреть файл

@ -234,8 +234,7 @@ namespace ShowcaseApp.WPF.Pages
if(_editorManager != null)
_editorManager.Dispose();
if(graphArea != null)
graphArea.Dispose();
graphArea.Dispose();
}
}

Просмотреть файл

@ -117,6 +117,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\NNGraph.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Pages\EditorGraph.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -200,6 +204,9 @@
<Compile Include="Pages\DebugGraph.xaml.cs">
<DependentUpon>DebugGraph.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\NNGraph.xaml.cs">
<DependentUpon>NNGraph.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EditorGraph.xaml.cs">
<DependentUpon>EditorGraph.xaml</DependentUpon>
</Compile>

Просмотреть файл

@ -20,29 +20,7 @@
BorderThickness="1"
CornerRadius="10,10,10,10"
Padding="{TemplateBinding Padding}">
<StackPanel Orientation="Vertical">
<Expander x:Name="exp" IsExpanded="True">
<ContentPresenter Content="{TemplateBinding Vertex}" />
</Expander>
<Button x:Name="btn" Tag="{Binding Path=Vertex.ID, RelativeSource={RelativeSource TemplatedParent}}"
Content="open" Width="50" Height="25" Margin="5">
<Button.ToolTip>
<ToolTip>
<StackPanel>
<TextBlock Text="{Binding Path=Vertex.ID, RelativeSource={RelativeSource TemplatedParent}}" Foreground="Black" />
</StackPanel>
</ToolTip>
</Button.ToolTip>
</Button>
</StackPanel>
<Border.Effect>
<DropShadowEffect BlurRadius="2" Color="LightGray"
Opacity="0.3" Direction="315"/>
</Border.Effect>
<ContentPresenter Content="{TemplateBinding Vertex}" />
</Border>
</ControlTemplate>
</Setter.Value>

Просмотреть файл

@ -11,6 +11,7 @@ using GraphX.Models;
using GraphX.PCL.Common.Enums;
using QuickGraph;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
@ -468,6 +469,23 @@ namespace GraphX
return vertexSizes;
}
public Dictionary<TVertex, Measure.Size> GetVertexSizesAndPositions(out IDictionary<TVertex, Measure.Point> vertexPositions)
{
//measure if needed and get all vertex sizes
if (!IsMeasureValid) Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var count = _vertexlist.Count(a => ((IGraphXVertex) a.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude);
var vertexSizes = new Dictionary<TVertex, Measure.Size>(count);
vertexPositions = new Dictionary<TVertex, Measure.Point>(count);
//go through the vertex presenters and get the actual layoutpositions
foreach (var vc in VertexList.Where(vc => ((IGraphXVertex)vc.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude))
{
vertexSizes[vc.Key] = new Measure.Size(vc.Value.ActualWidth, vc.Value.ActualHeight);
vertexPositions[vc.Key] = vc.Value.GetPositionGraphX();
}
return vertexSizes;
}
/// <summary>
/// Get visual vertex size rectangles (can be used by some algorithms)
/// </summary>
@ -553,6 +571,7 @@ namespace GraphX
Dictionary<TVertex, Measure.Rect> rectangles = null; //rectangled size data
IExternalOverlapRemoval<TVertex> overlap = null;//overlap removal algorithm
IExternalEdgeRouting<TVertex, TEdge> eralg = null;
IDictionary<TVertex, Measure.Point> vertexPositions = null;
if(!RunOnDispatcherThread(() =>
{
@ -565,8 +584,10 @@ namespace GraphX
UpdateLayout(); //update layout so we can get actual control sizes
if (LogicCore.AreVertexSizesNeeded())
vertexSizes = GetVertexSizes();
alg = LogicCore.GenerateLayoutAlgorithm(vertexSizes);
vertexSizes = GetVertexSizesAndPositions(out vertexPositions);
else vertexPositions = GetVertexPositions();
alg = LogicCore.GenerateLayoutAlgorithm(vertexSizes, vertexPositions);
if (alg == null && !LogicCore.IsCustomLayout)
{
MessageBox.Show("Layout type not supported yet!");
@ -594,7 +615,7 @@ namespace GraphX
else
{
//UpdateLayout();
resultCoords = GetVertexPositions();
resultCoords = vertexPositions;
}
//overlap removal
@ -1510,7 +1531,7 @@ namespace GraphX
// {
var vPositions = GetVertexPositions();
var vSizeRectangles = GetVertexSizeRectangles();
var lay = LogicCore.GenerateLayoutAlgorithm(GetVertexSizes());
var lay = LogicCore.GenerateLayoutAlgorithm(GetVertexSizes(), GetVertexPositions());
var or = LogicCore.GenerateOverlapRemovalAlgorithm(vSizeRectangles);
var er = LogicCore.GenerateEdgeRoutingAlgorithm(DesiredSize.ToGraphX(), vPositions, vSizeRectangles);
LogicCore.CreateNewAlgorithmStorage(lay, or, er);

Просмотреть файл

@ -18,6 +18,7 @@ using System.IO;
using System.Linq;
using GraphX.METRO.Controls.Enums;
using GraphX.METRO.Controls.Models.Interfaces;
using GraphX.PCL.Common.Enums;
namespace GraphX
@ -444,15 +445,31 @@ namespace GraphX
{
//measure if needed and get all vertex sizes
Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var vertexSizes = new Dictionary<TVertex, Measure.Size>(_vertexlist.Count);
var vertexSizes = new Dictionary<TVertex, Measure.Size>(_vertexlist.Count(a => ((IGraphXVertex)a.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude));
//go through the vertex presenters and get the actual layoutpositions
foreach (var vc in VertexList)
foreach (var vc in VertexList.Where(vc => ((IGraphXVertex)vc.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude))
{
vertexSizes[vc.Key] = new Measure.Size(vc.Value.ActualWidth, vc.Value.ActualHeight);
}
return vertexSizes;
}
public Dictionary<TVertex, Measure.Size> GetVertexSizesAndPositions(out IDictionary<TVertex, Measure.Point> vertexPositions)
{
//measure if needed and get all vertex sizes
Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var count = _vertexlist.Count(a => ((IGraphXVertex)a.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude);
var vertexSizes = new Dictionary<TVertex, Measure.Size>(count);
vertexPositions = new Dictionary<TVertex, Measure.Point>(count);
//go through the vertex presenters and get the actual layoutpositions
foreach (var vc in VertexList.Where(vc => ((IGraphXVertex)vc.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude))
{
vertexSizes[vc.Key] = new Measure.Size(vc.Value.ActualWidth, vc.Value.ActualHeight);
vertexPositions[vc.Key] = vc.Value.GetPositionGraphX();
}
return vertexSizes;
}
/// <summary>
/// Get visual vertex size rectangles (can be used by some algorithms)
/// </summary>
@ -467,7 +484,7 @@ namespace GraphX
if (vertexSizes == null) vertexSizes = GetVertexSizes();
if (positions == null) positions = GetVertexPositions();
var rectangles = new Dictionary<TVertex, Measure.Rect>();
foreach (var vertex in LogicCore.Graph.Vertices)
foreach (var vertex in LogicCore.Graph.Vertices.Where(vc => vc.SkipProcessing != ProcessingOptionEnum.Exclude))
{
Measure.Point position; Measure.Size size;
if (!positions.TryGetValue(vertex, out position) || !vertexSizes.TryGetValue(vertex, out size)) continue;
@ -483,7 +500,7 @@ namespace GraphX
/// </summary>
public Dictionary<TVertex, Measure.Point> GetVertexPositions()
{
return VertexList.ToDictionary(vertex => vertex.Key, vertex => vertex.Value.GetPositionGraphX());
return VertexList.Where(a => ((IGraphXVertex)a.Value.Vertex).SkipProcessing != ProcessingOptionEnum.Exclude).ToDictionary(vertex => vertex.Key, vertex => vertex.Value.GetPositionGraphX());
}
#endregion
@ -506,7 +523,7 @@ namespace GraphX
RemoveAllEdges();
//preload vertex controls
foreach (var it in graph.Vertices)
foreach (var it in graph.Vertices.Where(a => a.SkipProcessing != ProcessingOptionEnum.Exclude))
{
var vc = ControlFactory.CreateVertexControl(it);
vc.DataContext = dataContextToDataItem ? it : null;
@ -530,6 +547,7 @@ namespace GraphX
Dictionary<TVertex, Measure.Rect> rectangles = null; //rectangled size data
IExternalOverlapRemoval<TVertex> overlap = null; //overlap removal algorithm
IExternalEdgeRouting<TVertex, TEdge> eralg = null;
IDictionary<TVertex, Measure.Point> vertexPositions = null;
var result = false;
await DispatcherHelper.CheckBeginInvokeOnUi(() =>
@ -544,8 +562,10 @@ namespace GraphX
UpdateLayout(); //update layout so we can get actual control sizes
if (LogicCore.AreVertexSizesNeeded())
vertexSizes = GetVertexSizes();
alg = LogicCore.GenerateLayoutAlgorithm(vertexSizes);
vertexSizes = GetVertexSizesAndPositions(out vertexPositions);
else vertexPositions = GetVertexPositions();
alg = LogicCore.GenerateLayoutAlgorithm(vertexSizes, vertexPositions);
if (alg == null && !LogicCore.IsCustomLayout)
{
//await new MessageDialog("Layout type not supported yet!").ShowAsync();
@ -575,7 +595,7 @@ namespace GraphX
else
{
//UpdateLayout();
resultCoords = GetVertexPositions();
resultCoords = vertexPositions;
}
//overlap removal
@ -1402,7 +1422,7 @@ namespace GraphX
{
var vPositions = GetVertexPositions();
var vSizeRectangles = GetVertexSizeRectangles();
var lay = LogicCore.GenerateLayoutAlgorithm(GetVertexSizes());
var lay = LogicCore.GenerateLayoutAlgorithm(GetVertexSizes(), GetVertexPositions());
var or = LogicCore.GenerateOverlapRemovalAlgorithm(vSizeRectangles);
var er = LogicCore.GenerateEdgeRoutingAlgorithm(DesiredSize.ToGraphX(), vPositions, vSizeRectangles);
LogicCore.CreateNewAlgorithmStorage(lay, or, er);

Просмотреть файл

@ -47,7 +47,7 @@ namespace GraphX
bool AreVertexSizesNeeded();
bool AreOverlapNeeded();
IExternalLayout<TVertex> GenerateLayoutAlgorithm(Dictionary<TVertex, Size> vertexSizes);
IExternalLayout<TVertex> GenerateLayoutAlgorithm(Dictionary<TVertex, Size> vertexSizes, IDictionary<TVertex, Point> vertexPositions);
IExternalOverlapRemoval<TVertex> GenerateOverlapRemovalAlgorithm(Dictionary<TVertex, Rect> rectangles = null);
IExternalEdgeRouting<TVertex, TEdge> GenerateEdgeRoutingAlgorithm(Size desiredSize, IDictionary<TVertex, Point> positions = null, IDictionary<TVertex, Rect> rectangles = null);

Просмотреть файл

@ -9,7 +9,7 @@ namespace GraphX
/// </summary>
int ID { get; set; }
/// <summary>
/// Skip edge in algorithm calc and visual control generation
/// Skip object in algorithm calc and visual control generation
/// </summary>
ProcessingOptionEnum SkipProcessing { get; set; }
}

Просмотреть файл

@ -1,38 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using GraphX.GraphSharp.Algorithms.Layout;
using GraphX.GraphSharp.Algorithms.Layout.Simple.Circular;
using GraphX.Measure;
using GraphX.PCL.Common.Enums;
using QuickGraph;
namespace GraphX.GraphSharp.Algorithms.Layout.Simple.Circular
namespace GraphX.PCL.Logic.GraphXComponents.LayoutAlgorithms.Circular
{
public class CircularLayoutAlgorithm<TVertex, TEdge, TGraph> : DefaultParameterizedLayoutAlgorithmBase<TVertex, TEdge, TGraph, CircularLayoutParameters>
where TVertex : class
where TVertex : class, IIdentifiableGraphDataObject
where TEdge : IEdge<TVertex>
where TGraph : IBidirectionalGraph<TVertex, TEdge>
{
readonly IDictionary<TVertex, Size> sizes;
readonly IDictionary<TVertex, Size> _sizes;
public CircularLayoutAlgorithm( TGraph visitedGraph, IDictionary<TVertex, Point> vertexPositions, IDictionary<TVertex, Size> vertexSizes, CircularLayoutParameters parameters )
: base( visitedGraph, vertexPositions, parameters )
{
//Contract.Requires( vertexSizes != null );
//Contract.Requires( visitedGraph.Vertices.All( v => vertexSizes.ContainsKey( v ) ) );
sizes = vertexSizes;
_sizes = vertexSizes;
}
public override void Compute(CancellationToken cancellationToken)
{
//calculate the size of the circle
double perimeter = 0;
double[] halfSize = new double[VisitedGraph.VertexCount];
var usableVertices = VisitedGraph.Vertices.Where(v => v.SkipProcessing != ProcessingOptionEnum.Freeze).ToList();
//if we have empty input positions list we have to fill positions for frozen vertices manualy
if(VertexPositions.Count == 0)
foreach(var item in VisitedGraph.Vertices.Where(v => v.SkipProcessing == ProcessingOptionEnum.Freeze))
VertexPositions.Add(item, new Point());
double[] halfSize = new double[usableVertices.Count];
int i = 0;
foreach ( var v in VisitedGraph.Vertices )
foreach ( var v in usableVertices)
{
cancellationToken.ThrowIfCancellationRequested();
Size s = sizes[v];
Size s = _sizes[v];
halfSize[i] = Math.Sqrt( s.Width * s.Width + s.Height * s.Height ) * 0.5;
perimeter += halfSize[i] * 2;
i++;
@ -45,7 +51,7 @@ namespace GraphX.GraphSharp.Algorithms.Layout.Simple.Circular
//
double angle = 0, a;
i = 0;
foreach ( var v in VisitedGraph.Vertices )
foreach (var v in usableVertices)
{
cancellationToken.ThrowIfCancellationRequested();
@ -65,7 +71,7 @@ namespace GraphX.GraphSharp.Algorithms.Layout.Simple.Circular
//calculation
angle = 0;
i = 0;
foreach ( var v in VisitedGraph.Vertices )
foreach (var v in usableVertices)
{
cancellationToken.ThrowIfCancellationRequested();

Просмотреть файл

@ -14,6 +14,7 @@ using System.Collections.Generic;
using GraphX.GraphSharp.Algorithms.Layout.Compound.FDP;
using GraphX.GraphSharp.Algorithms.Layout.Compound;
using GraphX.GraphSharpComponents.EdgeRouting;
using GraphX.PCL.Logic.GraphXComponents.LayoutAlgorithms.Circular;
namespace GraphX.Logic.Models
{

Просмотреть файл

@ -39,9 +39,9 @@ namespace GraphX.Logic
}
}
public IExternalLayout<TVertex> GenerateLayoutAlgorithm(Dictionary<TVertex, Size> vertexSizes)
public IExternalLayout<TVertex> GenerateLayoutAlgorithm(Dictionary<TVertex, Size> vertexSizes, IDictionary<TVertex, Point> vertexPositions)
{
if (ExternalLayoutAlgorithm == null) return AlgorithmFactory.CreateLayoutAlgorithm(DefaultLayoutAlgorithm, Graph, null, vertexSizes, DefaultLayoutAlgorithmParams);
if (ExternalLayoutAlgorithm == null) return AlgorithmFactory.CreateLayoutAlgorithm(DefaultLayoutAlgorithm, Graph, vertexPositions, vertexSizes, DefaultLayoutAlgorithmParams);
var alg = ExternalLayoutAlgorithm;
if (alg.NeedVertexSizes) alg.VertexSizes = vertexSizes;
return alg;