LayOutComponentInBin ( IGraph oGraph, ICollection <IVertex> oVerticesInComponent, Rectangle oBinRectangle ) { Debug.Assert(oGraph != null); Debug.Assert(oVerticesInComponent != null); AssertValid(); oGraph.SetValue(ReservedMetadataKeys.LayOutTheseVerticesOnly, oVerticesInComponent); // Force the FruchtermanReingoldLayout class to randomize the vertices. LayoutMetadataUtil.MarkGraphAsNotLaidOut(oGraph); ILayout oLayout = new FruchtermanReingoldLayout(); oLayout.Margin = BinMargin; LayoutContext oLayoutContext = new LayoutContext(oBinRectangle); oLayout.LayOutGraph(oGraph, oLayoutContext); }
LayOutGraphCore ( IGraph graph, ICollection <IVertex> verticesToLayOut, LayoutContext layoutContext, BackgroundWorker backgroundWorker ) { Debug.Assert(graph != null); Debug.Assert(verticesToLayOut != null); Debug.Assert(verticesToLayOut.Count > 0); Debug.Assert(layoutContext != null); AssertValid(); Int32 iVertices = verticesToLayOut.Count; ICollection <IEdge> oEdgesToLayOut = GetEdgesToLayOut(graph, verticesToLayOut); // If the graph has already been laid out, use the current vertex // locations as initial values. if (!LayoutMetadataUtil.GraphHasBeenLaidOut(graph)) { // The graph has not been laid out. Randomize the locations of // those vertices that are not locked. RandomizeVertexLocations(verticesToLayOut, layoutContext, new Random(1)); } // Store required metadata on the graph's vertices and edges. InitializeMetadata(graph, verticesToLayOut); Rectangle oRectangle = layoutContext.GraphRectangle; Single fArea = oRectangle.Width * oRectangle.Height; Debug.Assert(iVertices > 0); // The algorithm in Figure 1 of the Fruchterman-Reingold paper doesn't // include the constant C, but it is included in the calculation for k // under the "Modelling the forces" section. Single k = m_fC * (Single)Math.Sqrt(fArea / (Single)iVertices); // The rectangle is guaranteed to have non-zero width and height, so // k should never be zero. Debug.Assert(k != 0); // Use the simple cooling algorithm suggested in the Fruchterman- // Reingold paper. Single fTemperature = oRectangle.Width / 10F; Debug.Assert(m_iIterations != 0); Single fTemperatureDecrement = fTemperature / (Single)m_iIterations; while (fTemperature > 0) { if (backgroundWorker != null && backgroundWorker.CancellationPending) { return(false); } // Calculate the attractive and repulsive forces between the // vertices. The results get written to metadata on the vertices. CalculateRepulsiveForces(verticesToLayOut, k); CalculateAttractiveForces(oEdgesToLayOut, k); Single fNextTemperature = fTemperature - fTemperatureDecrement; // Set the unbounded location of each vertex based on the vertex's // current location and the calculated forces. SetUnboundedLocations(verticesToLayOut, layoutContext, fTemperature, fNextTemperature > 0); // Decrease the temperature. fTemperature = fNextTemperature; } RemoveMetadata(graph, verticesToLayOut); return(true); }
LayOutSmallerComponentsInBins ( IGraph graph, ICollection <IVertex> verticesToLayOut, LayoutContext layoutContext, out ICollection <IVertex> remainingVertices, out Rectangle remainingRectangle ) { AssertValid(); remainingVertices = null; remainingRectangle = Rectangle.Empty; // This method modifies some of the graph's metadata. Save the // original metadata. Boolean bOriginalGraphHasBeenLaidOut = LayoutMetadataUtil.GraphHasBeenLaidOut(graph); ICollection <IVertex> oOriginalLayOutTheseVerticesOnly = (ICollection <IVertex>)graph.GetValue( ReservedMetadataKeys.LayOutTheseVerticesOnly, typeof(ICollection <IVertex>)); // Split the vertices into strongly connected components, sorted in // increasing order of vertex count. ConnectedComponentCalculator oConnectedComponentCalculator = new ConnectedComponentCalculator(); IList <LinkedList <IVertex> > oComponents = oConnectedComponentCalculator.CalculateStronglyConnectedComponents( verticesToLayOut, graph, true); Int32 iComponents = oComponents.Count; // This object will split the graph rectangle into bin rectangles. RectangleBinner oRectangleBinner = new RectangleBinner( layoutContext.GraphRectangle, m_iBinLength); Int32 iComponent = 0; for (iComponent = 0; iComponent < iComponents; iComponent++) { LinkedList <IVertex> oComponent = oComponents[iComponent]; Int32 iVerticesInComponent = oComponent.Count; if (iVerticesInComponent > m_iMaximumVerticesPerBin) { // The vertices in the remaining components should not be // binned. break; } Rectangle oBinRectangle; if (!oRectangleBinner.TryGetNextBin(out oBinRectangle)) { // There is no room for an additional bin rectangle. break; } // Lay out the component within the bin rectangle. LayOutComponentInBin(graph, oComponent, oBinRectangle); } // Restore the original metadata on the graph. if (bOriginalGraphHasBeenLaidOut) { LayoutMetadataUtil.MarkGraphAsLaidOut(graph); } else { LayoutMetadataUtil.MarkGraphAsNotLaidOut(graph); } if (oOriginalLayOutTheseVerticesOnly != null) { graph.SetValue(ReservedMetadataKeys.LayOutTheseVerticesOnly, oOriginalLayOutTheseVerticesOnly); } else { graph.RemoveKey(ReservedMetadataKeys.LayOutTheseVerticesOnly); } if (oRectangleBinner.TryGetRemainingRectangle( out remainingRectangle)) { remainingVertices = GetRemainingVertices(oComponents, iComponent); return(remainingVertices.Count > 0); } return(false); }