/// <summary> /// Creates a forest of unbalanced trees and applies a radial layout. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void RandomRadialForest(RadDiagram diagram, GraphGenerationSpecifications specs) { this.diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; var g = this.diagram.CreateDiagram(GraphExtensions.CreateRandomGraph(250, 4, true), out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.RadialTree, HorizontalSeparation = this.HorizontalSeparationSlider.Value, VerticalSeparation = this.VerticalSeparationSlider.Value, UnderneathHorizontalOffset = this.UnderneathHorizontalOffsetSlider.Value, UnderneathVerticalSeparation = this.UnderneathVerticalOffsetSlider.Value, KeepComponentsInOneRadialLayout = true, RadialSeparation = 45d }; var center = g.FindNode(0); settings.Roots.Add(nodeMap[center]); var layout = new TreeLayout(); layout.Layout(this.diagram, settings); this.diagram.AutoFit(); //Colorize(g, nodeMap, center); }
/// <summary> /// Creates a tree which grows symmetrically. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void BalancedRadialTree(RadDiagram diagram, GraphGenerationSpecifications specs) { this.diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; // the algorithm to create a balanced tree is quite straighforward var g = this.diagram.CreateDiagram(GraphExtensions.CreateBalancedTree(), out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); // the result is best displayed with the radial tree layout var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.RadialTree, HorizontalSeparation = this.HorizontalSeparationSlider.Value, VerticalSeparation = this.VerticalSeparationSlider.Value, UnderneathHorizontalOffset = this.UnderneathHorizontalOffsetSlider.Value, UnderneathVerticalSeparation = this.UnderneathVerticalOffsetSlider.Value, StartRadialAngle = Math.PI, // use a specific angle rather than the full 360° to show one of the layout's (hidden) gem EndRadialAngle = 3.47 * Math.PI / 2 }; var center = g.FindNode(-1); settings.Roots.Add(nodeMap[center]); var layout = new TreeLayout(); layout.Layout(this.diagram, settings); // center and size autimagically this.diagram.AutoFit(); // you can colorize the shapes, if you wish // this.Colorize(g, nodeMap, center); }
/// <summary> /// Creates a specific graph to show the shortest path between two nodes. /// </summary> /// <param name="obj">The diagram.</param> /// <param name="specs">The specs.</param> private void ShortestPath(RadDiagram obj, GraphGenerationSpecifications specs) { this.diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; var g = this.diagram.CreateDiagram(new List <string> { "1,2", "2,3", "1,4", "4,5", "5,3", "1,6", "6,7", "7,8", "8,3", "3,9", "9,10", "10,11" }, out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); // Dijkstra's algorithm will give you the shortest path var path = g.DijkstraShortestPath(1, 11); if (path != null) { this.Highlight(path, nodeMap, edgeMap, this.HighlighBrush); } // the node map gives us the shape from a node and we want to have the "1" node at the root of the tree var nodeOne = g.FindNode(1); var shapeOne = nodeMap[nodeOne]; var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeDown, VerticalSeparation = 50d, HorizontalSeparation = 80d, }; // specifying the root (or roots if we have a forest) can be done using the Roots property like so settings.Roots.Add(shapeOne); diagram.Layout(LayoutType.Tree, settings); }
/// <summary> /// Creates a random connected graph and displayes a (non-unique) spanning tree using Prim's algorithm. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void Prims(RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; var randomConnectedGraph = GraphExtensions.CreateRandomConnectedGraph(10); var root = randomConnectedGraph.FindTreeRoot(); var g = diagram.CreateDiagram(randomConnectedGraph, out nodeMap, out edgeMap, GraphExtensions.CreateShape, specs.RandomShapeSize); // making it undirected will reach all the nodes since the random graph is connected g.IsDirected = false; var tree = g.PrimsSpanningTree(root); if (tree != null) { this.Highlight(tree, nodeMap, edgeMap, this.HighlighBrush); } var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeDown, VerticalSeparation = 50d, HorizontalSeparation = 80d, }; diagram.Layout(LayoutType.Tree, settings); }
/// <summary> /// Creates a specific diagram and highlight the longest path found through the graph analysis. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void LongestPath(RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; // this creates the specific graph var g = this.diagram.CreateDiagram(new List <string> { "1,2", "2,3", "2,4", "3,5", "4,5", "5,6", "2,7", "7,8", "8,9", "9,10", "10,6", "20,21", "21,22", "20,25" }, out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); // note that this works on disconnected graphs as well as on connected ones var path = g.FindLongestPath(); // highlight the longest path if one is found if (path != null) { this.Highlight(path, nodeMap, edgeMap, this.HighlighBrush); } // use a layout which displays the result best diagram.Layout(LayoutType.Tree, new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeUp, VerticalSeparation = 80d, HorizontalSeparation = 50d }); }
/// <summary> /// Creates a specific graph which has some obvious cycles and lets the graph analysis highlight them, thus confirming the cycles /// which can be easily found manually. The analysis goes of course beyond what the human eye can see and would find cycles in an arbitrary graph. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void Cycles(RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; var g = diagram.CreateDiagram(new List <string> { "1,2", "3,1", "2,4", "4,3", "4,5", "10,11", "11,12", "12,10" }, out nodeMap, out edgeMap, specs.CreateShape, specs.RandomShapeSize); var cycles = g.FindCycles(); if (cycles.Count > 0) { foreach (var cycle in cycles) { var path = new GraphPath <Node, Edge>(); cycle.ToList().ForEach(path.AddNode); this.Highlight(path, nodeMap, edgeMap, specs.HighlightBrush); } } diagram.Layout(LayoutType.Tree, new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeRight, VerticalSeparation = 50d, HorizontalSeparation = 80d }); }
public static void CreateGraph(this RadDiagram diagram, GraphGenerationSpecifications specs, CreateShapeDelegate createShape) { diagram.Clear(); if (specs.Connections) { var g = specs.Connected ? GraphExtensions.CreateRandomConnectedGraph(specs.NodeCount, 4, specs.TreeGraph) : GraphExtensions.CreateRandomGraph(specs.NodeCount, 4, specs.TreeGraph); diagram.CreateDiagram(g, GraphExtensions.CreateShape, specs.RandomShapeSize); } else { for (var i = 0; i < specs.NodeCount; i++) { var shape = createShape(new Node(i, false), specs.RandomShapeSize); diagram.AddShape(shape); } } }
/// <summary> /// Creates a balanced radial forest. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> public static void BalancedRadialForest(this RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; var g = diagram.CreateDiagram(CreateBalancedForest(), out nodeMap, out edgeMap, CreateShape, specs.RandomShapeSize); var settings = new TreeLayoutSettings { TreeLayoutType = specs.TreeType, HorizontalSeparation = specs.HorizontalSeparation, VerticalSeparation = specs.VerticalSeparation, UnderneathHorizontalOffset = specs.UnderneathHorizontalOffset, UnderneathVerticalSeparation = specs.UnderneathVerticalSeparation, KeepComponentsInOneRadialLayout = specs.KeepComponentsInOneRadialLayout }; var center = g.FindNode(1); settings.Roots.Add(nodeMap[center]); var layout = new TreeLayout(); layout.Layout(diagram, settings); diagram.AutoFit(); }
/// <summary> /// Creates a balanced radial forest. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> public static void BalancedRadialForest(this RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary <Node, RadDiagramShape> nodeMap; Dictionary <Edge, RadDiagramConnection> edgeMap; var g = diagram.CreateDiagram(CreateBalancedForest(), out nodeMap, out edgeMap, CreateShape, specs.RandomShapeSize); var settings = new TreeLayoutSettings { TreeLayoutType = specs.TreeType, HorizontalSeparation = specs.HorizontalSeparation, VerticalSeparation = specs.VerticalSeparation, UnderneathHorizontalOffset = specs.UnderneathHorizontalOffset, UnderneathVerticalSeparation = specs.UnderneathVerticalSeparation, KeepComponentsInOneRadialLayout = specs.KeepComponentsInOneRadialLayout }; var center = g.FindNode(1); settings.Roots.Add(nodeMap[center]); var layout = new TreeLayout(); layout.Layout(diagram, settings); diagram.AutoFit(); }
/// <summary> /// Creates a forest of balanced radial tree and applies a radial layout. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private static void BalancedRadialForest(RadDiagram diagram, GraphGenerationSpecifications specs) { specs.TreeType = TreeLayoutType.RadialTree; specs.KeepComponentsInOneRadialLayout = true; diagram.BalancedRadialForest(specs); }
public static void CreateGraph(this RadDiagram diagram, GraphGenerationSpecifications specs, CreateShapeDelegate createShape) { diagram.Clear(); if (specs.Connections) { var g = specs.Connected ? GraphExtensions.CreateRandomConnectedGraph(specs.NodeCount, 4, specs.TreeGraph) : GraphExtensions.CreateRandomGraph(specs.NodeCount, 4, specs.TreeGraph); diagram.CreateDiagram(g, GraphExtensions.CreateShape, specs.RandomShapeSize); } else { for (var i = 0; i < specs.NodeCount; i++) { var shape = createShape(new Node(i, false), specs.RandomShapeSize, null); diagram.AddShape(shape); } } }
/// <summary> /// Creates a specific graph which has some obvious cycles and lets the graph analysis highlight them, thus confirming the cycles /// which can be easily found manually. The analysis goes of course beyond what the human eye can see and would find cycles in an arbitrary graph. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void Cycles(RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; var g = diagram.CreateDiagram(new List<string> { "1,2", "3,1", "2,4", "4,3", "4,5", "10,11", "11,12", "12,10" }, out nodeMap, out edgeMap, specs.CreateShape, specs.RandomShapeSize); var cycles = g.FindCycles(); if (cycles.Count > 0) { foreach (var cycle in cycles) { var path = new GraphPath<Node, Edge>(); cycle.ToList().ForEach(path.AddNode); this.Highlight(path, nodeMap, edgeMap, specs.HighlightBrush); } } diagram.Layout(LayoutType.Tree, new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeRight, VerticalSeparation = 50d, HorizontalSeparation = 80d }); }
/// <summary> /// Creates a specific diagram and highlight the longest path found through the graph analysis. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void LongestPath(RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; // this creates the specific graph var g = this.diagram.CreateDiagram(new List<string> { "1,2", "2,3", "2,4", "3,5", "4,5", "5,6", "2,7", "7,8", "8,9", "9,10", "10,6", "20,21", "21,22", "20,25" }, out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); // note that this works on disconnected graphs as well as on connected ones var path = g.FindLongestPath(); // highlight the longest path if one is found if (path != null) this.Highlight(path, nodeMap, edgeMap, this.HighlighBrush); // use a layout which displays the result best diagram.Layout(LayoutType.Tree, new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeUp, VerticalSeparation = 80d, HorizontalSeparation = 50d }); }
/// <summary> /// Creates a random connected graph and displayes a (non-unique) spanning tree using Prim's algorithm. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void Prims(RadDiagram diagram, GraphGenerationSpecifications specs) { diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; var randomConnectedGraph = GraphExtensions.CreateRandomConnectedGraph(10); var root = randomConnectedGraph.FindTreeRoot(); var g = diagram.CreateDiagram(randomConnectedGraph, out nodeMap, out edgeMap, GraphExtensions.CreateShape, specs.RandomShapeSize); // making it undirected will reach all the nodes since the random graph is connected g.IsDirected = false; var tree = g.PrimsSpanningTree(root); if (tree != null) this.Highlight(tree, nodeMap, edgeMap, this.HighlighBrush); var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeDown, VerticalSeparation = 50d, HorizontalSeparation = 80d, }; diagram.Layout(LayoutType.Tree, settings); }
/// <summary> /// Creates a forest of unbalanced trees and applies a radial layout. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void RandomRadialForest(RadDiagram diagram, GraphGenerationSpecifications specs) { this.diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; var g = this.diagram.CreateDiagram(GraphExtensions.CreateRandomGraph(250, 4, true), out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.RadialTree, HorizontalSeparation = this.HorizontalSeparationSlider.Value, VerticalSeparation = this.VerticalSeparationSlider.Value, UnderneathHorizontalOffset = this.UnderneathHorizontalOffsetSlider.Value, UnderneathVerticalSeparation = this.UnderneathVerticalOffsetSlider.Value, KeepComponentsInOneRadialLayout = true, RadialSeparation = 45d }; var center = g.FindNode(0); settings.Roots.Add(nodeMap[center]); var layout = new TreeLayout(); layout.Layout(this.diagram, settings); this.diagram.AutoFit(); //Colorize(g, nodeMap, center); }
/// <summary> /// Creates a specific graph to show the shortest path between two nodes. /// </summary> /// <param name="obj">The diagram.</param> /// <param name="specs">The specs.</param> private void ShortestPath(RadDiagram obj, GraphGenerationSpecifications specs) { this.diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; var g = this.diagram.CreateDiagram(new List<string> { "1,2", "2,3", "1,4", "4,5", "5,3", "1,6", "6,7", "7,8", "8,3", "3,9", "9,10", "10,11" }, out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); // Dijkstra's algorithm will give you the shortest path var path = g.DijkstraShortestPath(1, 11); if (path != null) this.Highlight(path, nodeMap, edgeMap, this.HighlighBrush); // the node map gives us the shape from a node and we want to have the "1" node at the root of the tree var nodeOne = g.FindNode(1); var shapeOne = nodeMap[nodeOne]; var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.TreeDown, VerticalSeparation = 50d, HorizontalSeparation = 80d, }; // specifying the root (or roots if we have a forest) can be done using the Roots property like so settings.Roots.Add(shapeOne); diagram.Layout(LayoutType.Tree, settings); }
/// <summary> /// Creates a tree which grows symmetrically. /// </summary> /// <param name="diagram">The diagram.</param> /// <param name="specs">The specs.</param> private void BalancedRadialTree(RadDiagram diagram, GraphGenerationSpecifications specs) { this.diagram.Clear(); Dictionary<Node, RadDiagramShape> nodeMap; Dictionary<Edge, RadDiagramConnection> edgeMap; // the algorithm to create a balanced tree is quite straighforward var g = this.diagram.CreateDiagram(GraphExtensions.CreateBalancedTree(), out nodeMap, out edgeMap, GraphExtensions.CreateShape, this.RandomSizeCheck.IsChecked.HasValue && this.RandomSizeCheck.IsChecked.Value); // the result is best displayed with the radial tree layout var settings = new TreeLayoutSettings { TreeLayoutType = TreeLayoutType.RadialTree, HorizontalSeparation = this.HorizontalSeparationSlider.Value, VerticalSeparation = this.VerticalSeparationSlider.Value, UnderneathHorizontalOffset = this.UnderneathHorizontalOffsetSlider.Value, UnderneathVerticalSeparation = this.UnderneathVerticalOffsetSlider.Value, StartRadialAngle = Math.PI, // use a specific angle rather than the full 360° to show one of the layout's (hidden) gem EndRadialAngle = 3.47 * Math.PI / 2 }; var center = g.FindNode(-1); settings.Roots.Add(nodeMap[center]); var layout = new TreeLayout(); layout.Layout(this.diagram, settings); // center and size autimagically this.diagram.AutoFit(); // you can colorize the shapes, if you wish // this.Colorize(g, nodeMap, center); }