private DirectedGraphViewModel CreateGraphViewModel(IGenome genome) { DirectedGraph digraph; float[] weightArr; INodeIdMap nodeIdByIdxMap; if (genome is NeatGenome <double> neatGenomeDouble) { digraph = neatGenomeDouble.DirectedGraph; weightArr = ToFloatArray(neatGenomeDouble.GetDigraphWeightArray()); nodeIdByIdxMap = neatGenomeDouble.NodeIndexByIdMap.CreateInverseMap(); } else if (genome is NeatGenome <float> neatGenomeFloat) { digraph = neatGenomeFloat.DirectedGraph; weightArr = neatGenomeFloat.GetDigraphWeightArray(); nodeIdByIdxMap = neatGenomeFloat.NodeIndexByIdMap.CreateInverseMap(); } else { throw new InvalidOperationException("The genome object is not a NeatGenome."); } DirectedGraphViewModel graphViewModel = new DirectedGraphViewModel(digraph, weightArr, nodeIdByIdxMap); return(graphViewModel); }
/// <summary> /// Paint the nodes of a directed graph. /// </summary> /// <param name="model">The graph view model being painted.</param> /// <param name="state">A collection of working variables for painting a graph to a GDI+ surface.</param> protected virtual void PaintNodes(DirectedGraphViewModel model, PaintState state) { // Loop the nodes, painting each in turn. for (int i = 0; i < model.NodeIdByIdx.Count; i++) { int id = model.NodeIdByIdx.Map(i); Point pos = model.NodePosByIdx ![i];
private static DirectedGraphViewModel CreateGraphViewModel() { // Simple acyclic graph. var connList = new List <WeightedDirectedConnection <float> > { new WeightedDirectedConnection <float>(0, 4, 1f), new WeightedDirectedConnection <float>(4, 5, 2f), new WeightedDirectedConnection <float>(5, 2, 3f), new WeightedDirectedConnection <float>(1, 2, 4f), new WeightedDirectedConnection <float>(2, 2, 5f), new WeightedDirectedConnection <float>(2, 3, 5f), new WeightedDirectedConnection <float>(2, 4, 5f), new WeightedDirectedConnection <float>(2, 5, 5f) }; connList.Sort(WeightedDirectedConnectionComparer <float> .Default); // Create graph. var digraph = WeightedDirectedGraphBuilder <float> .Create(connList, 2, 2); // Create graph view model, and return. INodeIdMap nodeIdByIdx = CreateNodeIdByIdx(digraph.TotalNodeCount); DirectedGraphViewModel graphViewModel = new DirectedGraphViewModel(digraph, digraph.WeightArray, nodeIdByIdx); return(graphViewModel); }
/// <summary> /// Paint a directed graph. /// </summary> /// <param name="model">The graph view model to paint.</param> /// <param name="state">A collection of working variables for painting a graph to a GDI+ surface.</param> protected virtual void PaintGraph(DirectedGraphViewModel model, PaintState state) { // Paint all connections, followed by all nodes. // This way the slightly 'rough' positioning of the connection endpoints is overpainted by the nodes // to produce an overall good visual result. PaintConnections(model, state); PaintNodes(model, state); }
/// <summary> /// Paint a directed graph onto the a provided GDI+ surface. /// </summary> /// <param name="model">The graph view model to paint.</param> /// <param name="g">The GDI+ surface to paint on to.</param> /// <param name="viewportArea">An area within the GDI+ surface to paint the graph within.</param> /// <param name="zoomFactor">Zoom factor.</param> public void PaintGraph( DirectedGraphViewModel model, Graphics g, Rectangle viewportArea, float zoomFactor) { PaintState state = new(g, viewportArea, _settings.NodeDiameter, zoomFactor, model.DirectedGraph.TotalNodeCount); PaintGraph(model, state); }
private void button1_Click(object sender, EventArgs e) { var graphViewportPainter = new GraphViewportPainter(); this.viewportControl1.ViewportPainter = graphViewportPainter; DirectedGraphViewModel graphViewModel = CreateGraphViewModel(); graphViewportPainter.GraphViewModel = graphViewModel; this.viewportControl1.RepaintViewport(); this.viewportControl1.Refresh(); }
public override void OnGenomeUpdated() { base.OnGenomeUpdated(); // Take a local reference to avoid possible race conditions on the class field. IGenome genome = _genome; if (genome is null) { _graphViewportPainter.GraphViewModel = null; } else { DirectedGraphViewModel graphViewModel = CreateGraphViewModel(genome); _graphViewportPainter.GraphViewModel = graphViewModel; } // Repaint the viewport. viewportControl1.RepaintViewport(); // Update the control/window to show the updated/repainted viewport. viewportControl1.Refresh(); }
public void Display(DirectionalGraphRenderer renderer) { if (renderer.DirectedWindowVM.RegenerateGraphView == false) { return; } DirectedGraphViewModel vm = new DirectedGraphViewModel(); double r = Math.Sqrt(Math.Pow(renderer.GraphControl.ActualHeight, 1.8) + Math.Pow(renderer.GraphControl.ActualWidth, 1.8)) / 20; for (int i = 0; i < renderer.Graph.NodesNr; ++i) { double ratio = (double)(renderer.Graph.NodeOrderInColumn(i)) / (double)(renderer.Graph.NodesInColumn(i) - 1); if (double.IsNaN(ratio) || double.IsInfinity(ratio)) { ratio = 0.0; } double x = r + (renderer.GraphControl.ActualWidth - 2 * r) * (double)(renderer.Graph.Columns[i]) / (double)(renderer.Graph.ColumnsCount()); double y = r + (renderer.GraphControl.ActualHeight - 2 * r) * ratio; vm.Nodes.Add(new CircleViewModel() { X = x, Y = y, Radius = r, Color = new SolidColorBrush(Colors.Yellow), Number = i + 1, NodeNumber = i }); } for (int y = 0; y < renderer.Graph.NodesNr; ++y) { for (int x = 0; x < renderer.Graph.NodesNr; ++x) { if (renderer.Graph.GetConnection(y, x) == false) { continue; } var ratio1 = (double)(renderer.Graph.NodeOrderInColumn(y)) / (double)(renderer.Graph.NodesInColumn(y) - 1); var ratio2 = (double)(renderer.Graph.NodeOrderInColumn(x)) / (double)(renderer.Graph.NodesInColumn(x) - 1); if (double.IsNaN(ratio1) || double.IsInfinity(ratio1)) { ratio1 = 0.0; } if (double.IsNaN(ratio2) || double.IsInfinity(ratio2)) { ratio2 = 0.0; } double x1 = r + (renderer.GraphControl.ActualWidth - 2 * r) * (double)(renderer.Graph.Columns[y]) / (double)(renderer.Graph.ColumnsCount()); double y1 = r + (renderer.GraphControl.ActualHeight - 2 * r) * ratio1; double x2 = r + (renderer.GraphControl.ActualWidth - 2 * r) * (double)(renderer.Graph.Columns[x]) / (double)(renderer.Graph.ColumnsCount()); double y2 = r + (renderer.GraphControl.ActualHeight - 2 * r) * ratio2; int maxFlow = 0; foreach (var flow in renderer.Graph.weights) { if (flow > 2000000) { continue; } if (flow > maxFlow) { maxFlow = flow; } } var abc = (float)renderer.Graph.getWeight(y, x); float flowRatio = ((float)renderer.Graph.getWeight(y, x) / (float)maxFlow); Color flowColor = Colors.Green; if (flowRatio <= 1.1) { flowColor = Color.FromRgb((byte)0, (byte)0, (byte)(flowRatio * 255)); } int thickness = 15; if (flowRatio <= 1.1) { thickness = (int)abc; } LineViewModel lineVM = new LineViewModel() { X1 = x1, Y1 = y1, X2 = x2, Y2 = y2, StartNode = y, EndNode = x, //Color = flowColor, Hint = string.Format("Flow {0}", abc), Thickness = thickness }; vm.Connections.Add(lineVM); double a = (y2 - y1) / (x2 - x1); double b = y2 / (a * x2); double length = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2)); double newLength = length - r / 2; double ratio = newLength / length; double newX = x1 + (x2 - x1) * ratio; double newY = y1 + (y2 - y1) * ratio; TriangleViewModel triangleVm = new TriangleViewModel() { X = newX - 10, Y = newY - 5, Angle = lineVM.Angle * (180.0 / Math.PI) + 90.0 }; vm.Triangles.Add(triangleVm); } } renderer.GraphControl.VM = vm; }
public void Display(DirectionalGraphRenderer renderer) { if (renderer.DirectedWindowVM.RegenerateGraphView == false) { return; } DirectedGraphViewModel vm = new DirectedGraphViewModel(); double r = Math.Sqrt(Math.Pow(renderer.GraphControl.ActualHeight, 1.8) + Math.Pow(renderer.GraphControl.ActualWidth, 1.8)) / 20; for (int i = 0; i < renderer.Graph.NodesNr; ++i) { double arc = 2 * Math.PI / renderer.Graph.NodesNr * i; double x = renderer.GraphControl.ActualWidth / 2 + (renderer.GraphControl.ActualWidth / 2 - r) * Math.Cos(arc); double y = renderer.GraphControl.ActualHeight / 2 + (renderer.GraphControl.ActualHeight / 2 - r) * Math.Sin(arc); vm.Nodes.Add(new CircleViewModel() { X = x, Y = y, Radius = r, Color = new SolidColorBrush(Colors.Yellow), Number = i + 1, NodeNumber = i }); } for (int y = 0; y < renderer.Graph.NodesNr; ++y) { for (int x = 0; x < renderer.Graph.NodesNr; ++x) { if (renderer.Graph.GetConnection(y, x) == false) { continue; } double arc1 = 2 * Math.PI / renderer.Graph.NodesNr * y; double arc2 = 2 * Math.PI / renderer.Graph.NodesNr * x; double x1 = renderer.GraphControl.ActualWidth / 2 + (renderer.GraphControl.ActualWidth / 2 - r) * Math.Cos(arc1); double y1 = renderer.GraphControl.ActualHeight / 2 + (renderer.GraphControl.ActualHeight / 2 - r) * Math.Sin(arc1); double x2 = renderer.GraphControl.ActualWidth / 2 + (renderer.GraphControl.ActualWidth / 2 - r) * Math.Cos(arc2); double y2 = renderer.GraphControl.ActualHeight / 2 + (renderer.GraphControl.ActualHeight / 2 - r) * Math.Sin(arc2); int weight = renderer.Graph.getWeight(y, x); byte redBrightness = 0; if (renderer.DirectedWindowVM.ShowWeights) { redBrightness = (byte)((Math.Abs(renderer.Graph.MaxWeight - renderer.Graph.MinWeight) - Math.Abs(renderer.Graph.MaxWeight - weight)) / (double)(Math.Abs(renderer.Graph.MaxWeight - renderer.Graph.MinWeight)) * 255.0); } LineViewModel lineVM = new LineViewModel() { X1 = x1, Y1 = y1, X2 = x2, Y2 = y2, StartNode = y, EndNode = x, Color = Color.FromRgb(redBrightness, 0, 0) }; vm.Connections.Add(lineVM); double a = (y2 - y1) / (x2 - x1); double b = y2 / (a * x2); double length = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2)); double newLength = length - r / 2; double ratio = newLength / length; double newX = x1 + (x2 - x1) * ratio; double newY = y1 + (y2 - y1) * ratio; TriangleViewModel triangleVm = new TriangleViewModel() { X = newX - 10, Y = newY - 5, Angle = lineVM.Angle * (180.0 / Math.PI) + 90.0 }; vm.Triangles.Add(triangleVm); if (renderer.DirectedWindowVM.ShowWeights) { LineViewModel hintVM = new LineViewModel(lineVM) { Hint = string.Format("Weight : {0}, {1} , {2}", weight, y, x), Color = Colors.Transparent, Thickness = 8 }; vm.Connections.Add(hintVM); } } } renderer.GraphControl.VM = vm; }