Skip to content
Snippets Groups Projects
Commit b06f2c8a authored by Timon Römer's avatar Timon Römer
Browse files

Fixes Graph Layout change after algorithm

parent e73b37a6
No related branches found
No related tags found
No related merge requests found
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABidirectionalGraph_002Ecs_002Fl_003AC_0021_003FUsers_003Fmp455017_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fa8e81c4118651b5932b855cf99986877c2c24685d864158c9053e4f62e213fce_003FBidirectionalGraph_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABidirectionalGraph_002Ecs_002Fl_003AC_0021_003FUsers_003Fmp455017_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fa8e81c4118651b5932b855cf99986877c2c24685d864158c9053e4f62e213fce_003FBidirectionalGraph_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIDictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fmp455017_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb756d57b94fb4ab9aa95a9b2a97fce1fa24ea0_003Fa1_003F8276683c_003FIDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEdge_002Ecs_002Fl_003AC_0021_003FUsers_003Ftimon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fc6dec8134d4e5115e30fcbbde23a657edc52dc4585c5673fe87fae89530f2_003FEdge_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
\ No newline at end of file <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIDictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fmp455017_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb756d57b94fb4ab9aa95a9b2a97fce1fa24ea0_003Fa1_003F8276683c_003FIDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003Ftimon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F362e998b40631a36346249d25c3c8c712372e68c65f251adc18f8931b4a77a32_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003Ftimon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F50b63217dc36f9d6edcabbd75adb3a7f68f1ebd3b4645b30614b43a9eda189_003FNode_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASplineRouter_002Ecs_002Fl_003AC_0021_003FUsers_003Ftimon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fb2961a4f945481bf9a55f7d27e451184c68497a74672874e415414929e5d53a_003FSplineRouter_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASugiyamaLayoutSettings_002Ecs_002Fl_003AC_0021_003FUsers_003Ftimon_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fe49262ac60bbccd8c34311e852def374298e4cf859347b2c83e6a6079f4e7e_003FSugiyamaLayoutSettings_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
\ No newline at end of file
...@@ -6,6 +6,12 @@ namespace FlowForge; ...@@ -6,6 +6,12 @@ namespace FlowForge;
public class FordFulkersonAlgorithm public class FordFulkersonAlgorithm
{ {
public enum SearchStrategy
{
BreadthFirstSearch,
DepthFirstSearch
}
private readonly FlowGraph _flowGraph; private readonly FlowGraph _flowGraph;
public FordFulkersonAlgorithm(FlowGraph flowGraph) public FordFulkersonAlgorithm(FlowGraph flowGraph)
...@@ -13,7 +19,7 @@ public class FordFulkersonAlgorithm ...@@ -13,7 +19,7 @@ public class FordFulkersonAlgorithm
_flowGraph = flowGraph; _flowGraph = flowGraph;
} }
public double Run(string sourceId, string targetId) public double Run(string sourceId, string targetId, SearchStrategy strategy=SearchStrategy.BreadthFirstSearch)
{ {
// get source and target nodes // get source and target nodes
FlowNode? source = _flowGraph.GetVertexById(sourceId); FlowNode? source = _flowGraph.GetVertexById(sourceId);
...@@ -35,7 +41,7 @@ public class FordFulkersonAlgorithm ...@@ -35,7 +41,7 @@ public class FordFulkersonAlgorithm
Console.WriteLine("Start of Ford-Fulkerson Algorithm..."); Console.WriteLine("Start of Ford-Fulkerson Algorithm...");
// execute as long as there is an augmenting path // execute as long as there is an augmenting path
while (FindAugmentingPathBfs(source, target, pathFlow)) while (FindAugmentingPath(source, target, pathFlow, strategy))
{ {
Console.WriteLine("Augmenting Path found:"); Console.WriteLine("Augmenting Path found:");
foreach (var edge in pathFlow.Keys) foreach (var edge in pathFlow.Keys)
...@@ -93,22 +99,32 @@ public class FordFulkersonAlgorithm ...@@ -93,22 +99,32 @@ public class FordFulkersonAlgorithm
return maxFlow; return maxFlow;
} }
private bool FindAugmentingPath(FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow, SearchStrategy strategy)
public bool FindAugmentingPathBfs(FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow)
{ {
// parent map to walk back path // parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>(); var parentMap = new Dictionary<FlowNode, FlowEdge>();
// queue for breath first search // Choose the appropriate data structure based on the strategy
IEnumerable<FlowNode> nodesToVisit;
if (strategy == SearchStrategy.BreadthFirstSearch)
{
var queue = new Queue<FlowNode>(); var queue = new Queue<FlowNode>();
queue.Enqueue(source); queue.Enqueue(source);
nodesToVisit = queue;
}
else
{
var stack = new Stack<FlowNode>();
stack.Push(source);
nodesToVisit = stack;
}
// map to store visited nodes // map to store visited nodes
var visited = new HashSet<FlowNode> { source }; var visited = new HashSet<FlowNode> { source };
while (queue.Count > 0) while (nodesToVisit.Any())
{ {
FlowNode current = queue.Dequeue(); var current = strategy == SearchStrategy.BreadthFirstSearch ? ((Queue<FlowNode>)nodesToVisit).Dequeue() : ((Stack<FlowNode>)nodesToVisit).Pop();
var outEdges = _flowGraph.Graph.OutEdges(current).ToList(); var outEdges = _flowGraph.Graph.OutEdges(current).ToList();
...@@ -125,58 +141,26 @@ public class FordFulkersonAlgorithm ...@@ -125,58 +141,26 @@ public class FordFulkersonAlgorithm
// if we reached the target node // if we reached the target node
if (currentEdge.Target.Equals(target)) if (currentEdge.Target.Equals(target))
{ {
FlowNode currentNode = target; BuildAugmentingPath(source, target, parentMap, pathFlow);
pathFlow.Clear();
while (currentNode != source)
{
FlowEdge pathEdge = parentMap[currentNode];
pathFlow.Add(pathEdge, pathEdge.Residual);
currentNode = pathEdge.Source;
}
// return the augmenting path found
return true; return true;
} }
// search further // search further
queue.Enqueue(currentEdge.Target); if (strategy == SearchStrategy.BreadthFirstSearch)
{
((Queue<FlowNode>)nodesToVisit).Enqueue(currentEdge.Target);
}
else
{
((Stack<FlowNode>)nodesToVisit).Push(currentEdge.Target);
}
} }
} }
return false; return false;
} }
public bool FindAugmentingPathDfs(FlowNode source, FlowNode target, Dictionary<FlowEdge, double> pathFlow) private static void BuildAugmentingPath(FlowNode source, FlowNode target, Dictionary<FlowNode, FlowEdge> parentMap, Dictionary<FlowEdge, double> pathFlow)
{
// parent map to walk back path
var parentMap = new Dictionary<FlowNode, FlowEdge>();
// queue for breath first search
var stack = new Stack<FlowNode>();
stack.Push(source);
// map to store visited nodes
var visited = new HashSet<FlowNode> { source };
while (stack.Count > 0)
{
FlowNode current = stack.Pop();
var outEdges = _flowGraph.Graph.OutEdges(current).ToList();
var sortedOutEdges = outEdges.OrderBy(edge => edge.Target.Id);
// go through all outgoing edges
foreach (FlowEdge currentEdge in sortedOutEdges)
{
if (currentEdge.Residual <= 0 || visited.Contains(currentEdge.Target)) continue;
visited.Add(currentEdge.Target);
parentMap.Add(currentEdge.Target, currentEdge);
// if we reached the target node
if (currentEdge.Target.Equals(target))
{ {
FlowNode currentNode = target; FlowNode currentNode = target;
pathFlow.Clear(); pathFlow.Clear();
...@@ -184,20 +168,8 @@ public class FordFulkersonAlgorithm ...@@ -184,20 +168,8 @@ public class FordFulkersonAlgorithm
while (currentNode != source) while (currentNode != source)
{ {
FlowEdge pathEdge = parentMap[currentNode]; FlowEdge pathEdge = parentMap[currentNode];
pathFlow.Add(pathEdge, pathEdge.Residual); pathFlow[pathEdge] = pathEdge.Residual;
currentNode = pathEdge.Source; currentNode = pathEdge.Source;
} }
// return the augmenting path found
return true;
}
// search further
stack.Push(currentEdge.Target);
} }
} }
\ No newline at end of file
return false;
}
}
...@@ -16,6 +16,8 @@ public static class GraphVisualizer ...@@ -16,6 +16,8 @@ public static class GraphVisualizer
foreach (var edge in flowGraph.Graph.Edges) foreach (var edge in flowGraph.Graph.Edges)
{ {
if(edge.IsBackwards) continue;
var msaglEdge = msaglGraph.AddEdge(edge.Source.Id, edge.Target.Id); var msaglEdge = msaglGraph.AddEdge(edge.Source.Id, edge.Target.Id);
if (edge.IsBackwards) if (edge.IsBackwards)
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="350,10,0,10" Margin="350,10,0,10"
Grid.Row="0" Grid.Row="0"
Click="RunAlgorithmButton_Click"/> Click="FordFulkersonButton_Click"/>
<!-- Second Button in the first row --> <!-- Second Button in the first row -->
<Button x:Name="RunEdmondsKarpButton" <Button x:Name="RunEdmondsKarpButton"
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="180,10,0,10" Margin="180,10,0,10"
Grid.Row="0" Grid.Row="0"
Click="RunAlgorithmButton_Click"/> Click="EdmondsKarpButton_Click"/>
<!-- Placeholder for graph viewer --> <!-- Placeholder for graph viewer -->
<Grid x:Name="GraphViewerGrid" Grid.Row="1"/> <Grid x:Name="GraphViewerGrid" Grid.Row="1"/>
......
using System; 
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms.Integration; using System.Windows.Forms.Integration;
using Microsoft.Msagl.Core.Geometry.Curves;
using Microsoft.Msagl.Core.Routing;
using MsaglDrawing = Microsoft.Msagl.Drawing; using MsaglDrawing = Microsoft.Msagl.Drawing;
using Microsoft.Msagl.GraphViewerGdi; using Microsoft.Msagl.GraphViewerGdi;
using Microsoft.Msagl.Layout.Layered;
using Microsoft.Msagl.Routing;
namespace FlowForge namespace FlowForge
{ {
...@@ -26,10 +20,13 @@ namespace FlowForge ...@@ -26,10 +20,13 @@ namespace FlowForge
private FlowGraph? _flowGraph; private FlowGraph? _flowGraph;
private FordFulkersonAlgorithm? _fordFulkerson; private FordFulkersonAlgorithm? _fordFulkerson;
private Dictionary<string, Microsoft.Msagl.Core.Geometry.Point> _nodePositions = new Dictionary<string, Microsoft.Msagl.Core.Geometry.Point>();
private MsaglDrawing.Graph _msaglGraph;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
InitializeGraph();
SetupGraphViewer(); SetupGraphViewer();
} }
...@@ -51,11 +48,59 @@ namespace FlowForge ...@@ -51,11 +48,59 @@ namespace FlowForge
// Event handler for "Initialize and Display Graph" button // Event handler for "Initialize and Display Graph" button
private void InitializeGraphButton_Click(object sender, RoutedEventArgs e) private void InitializeGraphButton_Click(object sender, RoutedEventArgs e)
{ {
InitializeGraph();
DisplayGraph(); DisplayGraph();
} }
// Event handler for "Run Ford-Fulkerson" button
private void FordFulkersonButton_Click(object sender, RoutedEventArgs e)
{
/*
// Move node "1" to position (100, 200)
_msaglGraph.FindNode("1").GeometryNode.Center = new Microsoft.Msagl.Core.Geometry.Point(20,700);
SetStraightLineEdges(_msaglGraph);
_gViewer.NeedToCalculateLayout = false;
_gViewer.Graph = _msaglGraph;*/
if (_gViewer != null) _gViewer.NeedToCalculateLayout = true;
SaveNodePositions(_gViewer?.Graph); // Save positions before running the algorithm
if (_fordFulkerson == null)
{
MessageBox.Show("Please initialize the graph first by clicking the 'Initialize Graph' button!", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
//SaveNodePositions(_gViewer.Graph); // Save positions before running the algorithm
double maxFlow = _fordFulkerson.Run("1", "4", FordFulkersonAlgorithm.SearchStrategy.DepthFirstSearch);
DisplayGraph();
MessageBox.Show($"Maximum flow from source to sink: {maxFlow}");
}
private void EdmondsKarpButton_Click(object sender, RoutedEventArgs e)
{
if (_fordFulkerson == null)
{
MessageBox.Show("Please initialize the graph first by clicking the 'Initialize Graph' button!", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
if (_gViewer != null) _gViewer.NeedToCalculateLayout = true;
SaveNodePositions(_gViewer?.Graph); // Save positions before running the algorithm
double maxFlow = _fordFulkerson.Run("1", "4", FordFulkersonAlgorithm.SearchStrategy.BreadthFirstSearch);
DisplayGraph();
MessageBox.Show($"Maximum flow from source to sink: {maxFlow}");
}
private void InitializeGraph() private void InitializeGraph()
{ {
if (_gViewer != null) _gViewer.NeedToCalculateLayout = true;
_nodePositions.Clear();
// Initialize a FlowGraph // Initialize a FlowGraph
_flowGraph = new FlowGraph(); _flowGraph = new FlowGraph();
...@@ -82,103 +127,126 @@ namespace FlowForge ...@@ -82,103 +127,126 @@ namespace FlowForge
private void DisplayGraph() private void DisplayGraph()
{ {
// Convert QuickGraph to MSAGL Graph // Convert QuickGraph to MSAGL Graph
var msaglGraph = GraphVisualizer.ConvertToMsaglGraph(_flowGraph); _msaglGraph = GraphVisualizer.ConvertToMsaglGraph(_flowGraph);
_msaglGraph.Attr.LayerDirection = MsaglDrawing.LayerDirection.TB;
// Farbe für Knoten 1 und 4 festlegen // Farbe für Knoten 1 und 4 festlegen
var node1 = msaglGraph.FindNode("1"); var node1 = _msaglGraph.FindNode("1");
if (node1 != null) if (node1 != null)
{ {
node1.Attr.FillColor = MsaglDrawing.Color.Green; // Knoten 1 wird grün node1.Attr.FillColor = MsaglDrawing.Color.Green; // Knoten 1 wird grün
} }
var node4 = msaglGraph.FindNode("4"); var node4 = _msaglGraph.FindNode("4");
if (node4 != null) if (node4 != null)
{ {
node4.Attr.FillColor = MsaglDrawing.Color.Red; // Knoten 4 wird rot node4.Attr.FillColor = MsaglDrawing.Color.Red; // Knoten 4 wird rot
} }
foreach (var node in msaglGraph.Nodes) foreach (var node in _msaglGraph.Nodes)
{ {
node.Attr.Shape = MsaglDrawing.Shape.Circle; // Knoten als Kreis node.Attr.Shape = MsaglDrawing.Shape.Circle; // Knoten als Kreis
} }
foreach (var edge in msaglGraph.Edges) foreach (var edge in _msaglGraph.Edges)
{ {
if (edge.Label != null) if (edge.Label != null)
{ {
edge.Label.FontSize = 4; // Setze die Schriftgröße des Kantenlabels auf 8 edge.Label.FontSize = 4; // Setze die Schriftgröße des Kantenlabels auf 4
} }
} }
// Assign MSAGL graph to viewer for display // Assign MSAGL graph to viewer for display
if (_gViewer != null) if (_gViewer != null)
{ {
_gViewer.Graph = msaglGraph;
}
}
_gViewer.Graph = _msaglGraph;
// Event handler for "Run Ford-Fulkerson" button if (_nodePositions.Any())
private void RunAlgorithmButton_Click(object sender, RoutedEventArgs e)
{
if (_fordFulkerson == null)
{ {
MessageBox.Show("Please initialize the graph first by clicking the 'Initialize Graph' button!", "Error", MessageBoxButton.OK, MessageBoxImage.Error); var originalScale = _gViewer.ZoomF;
return;
}
double maxFlow = _fordFulkerson.Run("1", "4"); ApplyNodePositions(_msaglGraph);
MessageBox.Show($"Maximaler Fluss von Quelle zu Senke: {maxFlow}"); var sugiyamaSettings = new SugiyamaLayoutSettings
{
};
/*
// Dictionary to store the flow along the augmenting path
var pathFlow = new Dictionary<FlowEdge, double>();
// Try to find an augmenting path from source (1) to target (4)
bool pathFound = _fordFulkerson.FindAugmentingPath(_flowGraph.GetVertexById("1"), _flowGraph.GetVertexById("4"), pathFlow);
if (pathFound) // Step 3: Apply layout settings to the graph
{ _msaglGraph.LayoutAlgorithmSettings = sugiyamaSettings;
// Find the start and end nodes
var source = _flowGraph.GetVertexById("1");
var target = _flowGraph.GetVertexById("4");
Console.WriteLine("Augmenting path found:"); _msaglGraph.LayoutAlgorithmSettings.EdgeRoutingSettings.RouteMultiEdgesAsBundles = false;
// To print in correct order, traverse the path from target to source var router = new SplineRouter(
var pathInOrder = new List<FlowEdge>(); _msaglGraph.GeometryGraph,
var current = target; _msaglGraph.LayoutAlgorithmSettings.EdgeRoutingSettings
);
router.Run();
// We trace back from the target to the source using the edges stored in pathFlow foreach (var edge in _msaglGraph.Edges)
while (current != source)
{ {
var edge = pathFlow.Keys.FirstOrDefault(e => e.Target == current); if (edge.GeometryEdge != null && edge.Label != null)
if (edge == null) continue; {
// Set the label to the midpoint of the edge path
edge.Label.GeometryLabel.Center = edge.GeometryEdge.Curve.BoundingBox.Center;
}
}
//SetStraightLineEdges(_msaglGraph);
pathInOrder.Insert(0, edge); // Insert the edge at the beginning to reverse the order _gViewer.ZoomF = originalScale;
current = edge.Source; // Move to the previous node
_gViewer.Invalidate();
_gViewer.NeedToCalculateLayout = false;
_gViewer.Graph = _msaglGraph;
}
}
} }
// Now we print the path from source to target in order private void SaveNodePositions(MsaglDrawing.Graph? msaglGraph)
foreach (var edge in pathInOrder) {
_nodePositions.Clear();
foreach (var node in msaglGraph.Nodes)
{ {
Console.WriteLine($"{edge.Source.Id} -> {edge.Target.Id}, Remaining Flow: {pathFlow[edge]}"); var position = node.GeometryNode.Center;
_nodePositions[node.Id] = new Microsoft.Msagl.Core.Geometry.Point(position.X, position.Y);
} }
} }
else
private void ApplyNodePositions(MsaglDrawing.Graph msaglGraph)
{ {
Console.WriteLine("No augmenting path found."); foreach (var node in msaglGraph.Nodes)
{
if (_nodePositions.TryGetValue(node.Id, out var position))
{
node.GeometryNode.Center = new Microsoft.Msagl.Core.Geometry.Point(position.X, position.Y);
}
}
} }
*/
// Run the Ford-Fulkerson algorithm private void SetStraightLineEdges(MsaglDrawing.Graph msaglGraph)
//double maxFlow = _fordFulkerson.Run("1", "4"); {
//MessageBox.Show($"Calculated Maximum Flow from Source to Sink: {maxFlow}"); var geometryGraph = msaglGraph.GeometryGraph;
// Update the visualization (optional) foreach (var edge in geometryGraph.Edges)
DisplayGraph(); {
var sourceCenter = edge.Source.Center;
var targetCenter = edge.Target.Center;
// Create a straight line from source to target
// Create a straight line from source to target
edge.Curve = new LineSegment(sourceCenter, targetCenter);
edge.LineWidth = 2;
}
foreach (var edge in msaglGraph.Edges)
{
edge.Attr.ArrowheadAtTarget = MsaglDrawing.ArrowStyle.Normal; // Ensure arrowhead is displayed
edge.Attr.ArrowheadLength = 1;
}
} }
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment