SaveGraphCore ( IGraph graph, Stream stream ) { Debug.Assert(graph != null); Debug.Assert(stream != null); AssertValid(); // The Pajek format requires coordinates to be between 0 and 1.0. Get // a Matrix that will transform the vertex locations to this range. RectangleF oCurrentBoundingRectangle = LayoutUtil.GetGraphBoundingRectangle(graph); RectangleF oNewBoundingRectangle = new RectangleF(PointF.Empty, new SizeF(1.0F, 1.0F)); Matrix oRectangleTransformation = LayoutUtil.GetRectangleTransformation( oCurrentBoundingRectangle, oNewBoundingRectangle ); // Create a dictionary to keep track of vertices. The keys are vertex // IDs and the values are the one-based vertex numbers used by the // Pajek format. Dictionary <Int32, Int32> oVertexIDToNumber = new Dictionary <Int32, Int32>(); IVertexCollection oVertices = graph.Vertices; StreamWriter oStreamWriter = new StreamWriter(stream, StreamEncoding); // Add the *vertices section. oStreamWriter.WriteLine( "*vertices {0}" , oVertices.Count ); Int32 iVertexNumber = 1; foreach (IVertex oVertex in oVertices) { // Format: // // 1 "vertex 1 name" x y z // Transform the vertex location. PointF oTransformedLocation = LayoutUtil.TransformPointF( oVertex.Location, oRectangleTransformation); // Limit the range in case of rounding errors. Single fX = Math.Max(0F, oTransformedLocation.X); fX = Math.Min(1F, fX); Single fY = Math.Max(0F, oTransformedLocation.Y); fY = Math.Min(1F, fY); oStreamWriter.WriteLine( "{0} \"{1}\" {2:N6} {3:N6} 0" , iVertexNumber, oVertex.Name, fX, fY ); oVertexIDToNumber.Add(oVertex.ID, iVertexNumber); iVertexNumber++; } IEdgeCollection oEdges = graph.Edges; GraphDirectedness eDirectedness = graph.Directedness; Boolean bSectionNameWritten = false; if (eDirectedness != GraphDirectedness.Directed) { // If appropriate, add the *edges section, which specifies // undirected edges. foreach (IEdge oEdge in oEdges) { // The graph could be mixed. if (oEdge.IsDirected) { continue; } if (!bSectionNameWritten) { oStreamWriter.WriteLine("*edges"); bSectionNameWritten = true; } WriteEdge(oEdge, oVertexIDToNumber, oStreamWriter); } } bSectionNameWritten = false; if (eDirectedness != GraphDirectedness.Undirected) { // If appropriate, add the *arcs section, which specifies // directed edges. foreach (IEdge oEdge in oEdges) { // The graph could be mixed. if (!oEdge.IsDirected) { continue; } if (!bSectionNameWritten) { oStreamWriter.WriteLine("*arcs"); bSectionNameWritten = true; } WriteEdge(oEdge, oVertexIDToNumber, oStreamWriter); } } oStreamWriter.Flush(); }