Example #1
0
        /// <summary>
        /// Writes a GEXF graph file for the specified graph nodes and edges
        /// </summary>
        /// <param name="Filename">The file name to write</param>
        /// <param name="Description">The description to include in the graph file's metadata</param>
        /// <param name="GraphNodes">List of all graph nodes.  Index order is important and must match with the individual node Id members!</param>
        /// <param name="GraphEdges">List of all graph edges.  Index order is important and must match with the individual edge Id members!</param>
        public static void WriteGraphFile(string Filename, string Description, List <GraphNode> GraphNodes, List <GraphEdge> GraphEdges)
        {
            XmlWriterSettings Settings = new XmlWriterSettings();

            Settings.Indent      = true;
            Settings.IndentChars = "    ";

            // Figure out all of the custom attribute types we're dealing with
            Dictionary <string, GraphAttribute> AllAttributes = new Dictionary <string, GraphAttribute>(StringComparer.InvariantCultureIgnoreCase);
            int NextAttributeID = 0;

            foreach (GraphNode GraphNode in GraphNodes)
            {
                foreach (string AttributeName in GraphNode.Attributes.Keys)
                {
                    object AttributeValue = GraphNode.Attributes[AttributeName];

                    string AttributeTypeName;
                    if (AttributeValue.GetType() == typeof(int))
                    {
                        AttributeTypeName = "integer";
                    }
                    else if (AttributeValue.GetType() == typeof(float))
                    {
                        AttributeTypeName = "float";
                    }
                    else if (AttributeValue.GetType() == typeof(double))
                    {
                        AttributeTypeName = "double";
                    }
                    else if (AttributeValue.GetType() == typeof(string))
                    {
                        AttributeTypeName = "string";
                    }
                    else if (AttributeValue.GetType() == typeof(bool))
                    {
                        AttributeTypeName = "boolean";
                    }
                    else
                    {
                        // No other types supported yet!
                        throw new InvalidOperationException("Unsupported attribute data type encountered on graph node!");
                    }


                    GraphAttribute Attribute;
                    if (!AllAttributes.TryGetValue(AttributeName, out Attribute))
                    {
                        Attribute          = new GraphAttribute();
                        Attribute.ID       = NextAttributeID++;
                        Attribute.Name     = AttributeName;
                        Attribute.TypeName = AttributeTypeName;

                        AllAttributes[AttributeName] = Attribute;
                    }
                    else
                    {
                        if (!Attribute.TypeName.Equals(AttributeTypeName))
                        {
                            throw new InvalidOperationException("Multiple graph nodes with the same attribute name but different types encountered!");
                        }
                    }
                }
            }


            using (XmlWriter Writer = XmlWriter.Create(Filename, Settings))
            {
                // NOTE: The GEXF XML format is defined here:  http://gexf.net/1.2draft/gexf-12draft-primer.pdf

                string GEXFNamespace   = "http://www.gexf.net/1.2-draft";
                string SchemaNamespace = "http://www.w3.org/2001/XMLSchema-instance";
                string VizNamespace    = "http://www.gexf.net/1.2draft/viz";

                Writer.WriteStartElement("gexf", GEXFNamespace);
                Writer.WriteAttributeString("xmlns", "xsi", null, SchemaNamespace);
                Writer.WriteAttributeString("schemaLocation", SchemaNamespace, "http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd");
                Writer.WriteAttributeString("xmlns", "viz", null, VizNamespace);
                Writer.WriteAttributeString("version", "1.2");

                Writer.WriteStartElement("meta");
                {
                    Writer.WriteAttributeString("creator", "UnrealBuildTool");
                    Writer.WriteAttributeString("description", Description);
                }
                Writer.WriteEndElement();                       // meta

                {
                    Writer.WriteStartElement("graph");
                    {
                        Writer.WriteAttributeString("mode", "static");
                        Writer.WriteAttributeString("defaultedgetype", "directed");

                        if (AllAttributes.Count > 0)
                        {
                            Writer.WriteStartElement("attributes");
                            {
                                // @todo: Add support for edge attributes, not just node attributes
                                Writer.WriteAttributeString("class", "node");                                   // Node attributes, not edges!

                                foreach (GraphAttribute Attribute in AllAttributes.Values)
                                {
                                    Writer.WriteStartElement("attribute");
                                    {
                                        Writer.WriteAttributeString("id", Attribute.ID.ToString());
                                        Writer.WriteAttributeString("title", Attribute.Name);
                                        Writer.WriteAttributeString("type", Attribute.TypeName);
                                    }
                                    Writer.WriteEndElement();                                           // attribute
                                }

                                // @todo: Add support for attribute type default values
                            }
                            Writer.WriteEndElement();                                   // attributes
                        }

                        Writer.WriteStartElement("nodes");
                        {
                            foreach (GraphNode GraphNode in GraphNodes)
                            {
                                Writer.WriteStartElement("node");
                                {
                                    Writer.WriteAttributeString("id", GraphNode.Id.ToString());
                                    Writer.WriteAttributeString("label", GraphNode.Label);

                                    Writer.WriteStartElement("color", VizNamespace);
                                    {
                                        Writer.WriteAttributeString("r", ((int)(GraphNode.Color.R * 255.0f)).ToString());
                                        Writer.WriteAttributeString("g", ((int)(GraphNode.Color.G * 255.0f)).ToString());
                                        Writer.WriteAttributeString("b", ((int)(GraphNode.Color.B * 255.0f)).ToString());
                                        Writer.WriteAttributeString("a", GraphNode.Color.A.ToString());
                                    }
                                    Writer.WriteEndElement();                                           // viz:color

                                    Writer.WriteStartElement("size", VizNamespace);
                                    {
                                        Writer.WriteAttributeString("value", GraphNode.Size.ToString());
                                    }
                                    Writer.WriteEndElement();                                           // viz:size

                                    Writer.WriteStartElement("shape", VizNamespace);
                                    {
                                        // NOTE: Valid shapes are:  disc, square, triangle, diamond, image
                                        Writer.WriteAttributeString("value", "disc");
                                    }
                                    Writer.WriteEndElement();                                           // viz:shape

                                    if (GraphNode.Attributes.Count > 0)
                                    {
                                        Writer.WriteStartElement("attvalues");
                                        {
                                            foreach (KeyValuePair <string, object> AttributeHashEntry in GraphNode.Attributes)
                                            {
                                                string AttributeName  = AttributeHashEntry.Key;
                                                object AttributeValue = AttributeHashEntry.Value;

                                                GraphAttribute Attribute = AllAttributes[AttributeName];

                                                Writer.WriteStartElement("attvalue");
                                                {
                                                    Writer.WriteAttributeString("for", Attribute.ID.ToString());
                                                    Writer.WriteAttributeString("value", AttributeValue.ToString());
                                                }
                                                Writer.WriteEndElement();
                                            }
                                        }
                                        Writer.WriteEndElement();                                               // attvalues
                                    }
                                }
                                Writer.WriteEndElement();                                       // node
                            }
                        }
                        Writer.WriteEndElement();                               // nodes


                        Writer.WriteStartElement("edges");
                        {
                            foreach (GraphEdge GraphEdge in GraphEdges)
                            {
                                Writer.WriteStartElement("edge");
                                {
                                    Writer.WriteAttributeString("id", GraphEdge.Id.ToString());
                                    Writer.WriteAttributeString("source", GraphEdge.Source.Id.ToString());
                                    Writer.WriteAttributeString("target", GraphEdge.Target.Id.ToString());
                                    Writer.WriteAttributeString("weight", GraphEdge.Weight.ToString());

                                    Writer.WriteStartElement("color", VizNamespace);
                                    {
                                        Writer.WriteAttributeString("r", ((int)(GraphEdge.Color.R * 255.0f)).ToString());
                                        Writer.WriteAttributeString("g", ((int)(GraphEdge.Color.G * 255.0f)).ToString());
                                        Writer.WriteAttributeString("b", ((int)(GraphEdge.Color.B * 255.0f)).ToString());
                                        Writer.WriteAttributeString("a", GraphEdge.Color.A.ToString());
                                    }
                                    Writer.WriteEndElement();                                           // viz:color

                                    Writer.WriteStartElement("thickness", VizNamespace);
                                    {
                                        Writer.WriteAttributeString("value", GraphEdge.Thickness.ToString());
                                    }
                                    Writer.WriteEndElement();                                           // viz:thickness

                                    Writer.WriteStartElement("shape", VizNamespace);
                                    {
                                        // NOTE: Valid shapes are:  solid, dotted, dashed, double
                                        Writer.WriteAttributeString("value", "solid");
                                    }
                                    Writer.WriteEndElement();                                   // viz:shape
                                }
                                Writer.WriteEndElement();                                       // edge
                            }
                        }
                        Writer.WriteEndElement();                               // nodes
                    }

                    Writer.WriteEndElement();                   // graph
                }
                Writer.WriteEndElement();                       // gexf

                Writer.Flush();
            }
        }
        /// <summary>
        /// Writes a GEXF graph file for the specified graph nodes and edges
        /// </summary>
        /// <param name="Filename">The file name to write</param>
        /// <param name="Description">The description to include in the graph file's metadata</param>
        /// <param name="GraphNodes">List of all graph nodes.  Index order is important and must match with the individual node Id members!</param>
        /// <param name="GraphEdges">List of all graph edges.  Index order is important and must match with the individual edge Id members!</param>
        public static void WriteGraphFile( string Filename, string Description, List<GraphNode> GraphNodes, List<GraphEdge> GraphEdges )
        {
            var Settings = new XmlWriterSettings();
            Settings.Indent = true;
            Settings.IndentChars = "    ";

            // Figure out all of the custom attribute types we're dealing with
            var AllAttributes = new Dictionary<string, GraphAttribute>( StringComparer.InvariantCultureIgnoreCase );
            int NextAttributeID = 0;
            foreach( var GraphNode in GraphNodes )
            {
                foreach( var AttributeName in GraphNode.Attributes.Keys )
                {
                    var AttributeValue = GraphNode.Attributes[ AttributeName ];

                    string AttributeTypeName;
                    if( AttributeValue.GetType() == typeof(int) )
                    {
                        AttributeTypeName = "integer";
                    }
                    else if( AttributeValue.GetType() == typeof(float) )
                    {
                        AttributeTypeName = "float";
                    }
                    else if( AttributeValue.GetType() == typeof(double) )
                    {
                        AttributeTypeName = "double";
                    }
                    else if( AttributeValue.GetType() == typeof(string) )
                    {
                        AttributeTypeName = "string";
                    }
                    else if( AttributeValue.GetType() == typeof(bool) )
                    {
                        AttributeTypeName = "boolean";
                    }
                    else
                    {
                        // No other types supported yet!
                        throw new InvalidOperationException( "Unsupported attribute data type encountered on graph node!" );
                    }

                    GraphAttribute Attribute;
                    if( !AllAttributes.TryGetValue( AttributeName, out Attribute ) )
                    {
                        Attribute = new GraphAttribute();
                        Attribute.ID = NextAttributeID++;
                        Attribute.Name = AttributeName;
                        Attribute.TypeName = AttributeTypeName;

                        AllAttributes[ AttributeName ] = Attribute;
                    }
                    else
                    {
                        if( !Attribute.TypeName.Equals( AttributeTypeName ) )
                        {
                            throw new InvalidOperationException( "Multiple graph nodes with the same attribute name but different types encountered!");
                        }
                    }
                }
            }

            using( var Writer = XmlWriter.Create( Filename, Settings ) )
            {
                // NOTE: The GEXF XML format is defined here:  http://gexf.net/1.2draft/gexf-12draft-primer.pdf

                var GEXFNamespace = "http://www.gexf.net/1.2-draft";
                var SchemaNamespace = "http://www.w3.org/2001/XMLSchema-instance";
                var VizNamespace = "http://www.gexf.net/1.2draft/viz";

                Writer.WriteStartElement( "gexf", GEXFNamespace );
             				Writer.WriteAttributeString( "xmlns", "xsi", null, SchemaNamespace );
             				Writer.WriteAttributeString( "schemaLocation", SchemaNamespace, "http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd" );
                Writer.WriteAttributeString( "xmlns", "viz", null, VizNamespace );
             				Writer.WriteAttributeString( "version", "1.2" );

                Writer.WriteStartElement( "meta" );
                {
                    Writer.WriteAttributeString( "creator", "UnrealBuildTool" );
                    Writer.WriteAttributeString( "description", Description );
                }
                Writer.WriteEndElement();	// meta

                {
                    Writer.WriteStartElement( "graph" );
                    {
                        Writer.WriteAttributeString( "mode", "static" );
                        Writer.WriteAttributeString( "defaultedgetype", "directed" );

                        if( AllAttributes.Count > 0 )
                        {
                            Writer.WriteStartElement( "attributes" );
                            {
                                // @todo: Add support for edge attributes, not just node attributes
                                Writer.WriteAttributeString( "class", "node" );	// Node attributes, not edges!

                                foreach( var Attribute in AllAttributes.Values )
                                {
                                    Writer.WriteStartElement( "attribute" );
                                    {
                                        Writer.WriteAttributeString( "id", Attribute.ID.ToString() );
                                        Writer.WriteAttributeString( "title", Attribute.Name );
                                        Writer.WriteAttributeString( "type", Attribute.TypeName );
                                    }
                                    Writer.WriteEndElement();	// attribute
                                }

                                // @todo: Add support for attribute type default values
                            }
                            Writer.WriteEndElement();	// attributes

                        }

                        Writer.WriteStartElement( "nodes" );
                        {
                            foreach( var GraphNode in GraphNodes )
                            {
                                Writer.WriteStartElement( "node" );
                                {
                                    Writer.WriteAttributeString( "id", GraphNode.Id.ToString() );
                                    Writer.WriteAttributeString( "label", GraphNode.Label );

                                    Writer.WriteStartElement( "color", VizNamespace );
                                    {
                                        Writer.WriteAttributeString( "r", ((int)( GraphNode.Color.R * 255.0f )).ToString() );
                                        Writer.WriteAttributeString( "g", ((int)( GraphNode.Color.G * 255.0f )).ToString() );
                                        Writer.WriteAttributeString( "b", ((int)( GraphNode.Color.B * 255.0f )).ToString() );
                                        Writer.WriteAttributeString( "a", GraphNode.Color.A.ToString() );
                                    }
                                    Writer.WriteEndElement();	// viz:color

                                    Writer.WriteStartElement( "size", VizNamespace );
                                    {
                                        Writer.WriteAttributeString( "value", GraphNode.Size.ToString() );
                                    }
                                    Writer.WriteEndElement();	// viz:size

                                    Writer.WriteStartElement( "shape", VizNamespace );
                                    {
                                        // NOTE: Valid shapes are:  disc, square, triangle, diamond, image
                                        Writer.WriteAttributeString( "value", "disc" );
                                    }
                                    Writer.WriteEndElement();	// viz:shape

                                    if( GraphNode.Attributes.Count > 0 )
                                    {
                                        Writer.WriteStartElement( "attvalues" );
                                        {
                                            foreach( var AttributeHashEntry in GraphNode.Attributes )
                                            {
                                                var AttributeName = AttributeHashEntry.Key;
                                                var AttributeValue = AttributeHashEntry.Value;

                                                var Attribute = AllAttributes[ AttributeName ];

                                                Writer.WriteStartElement( "attvalue" );
                                                {
                                                    Writer.WriteAttributeString( "for", Attribute.ID.ToString() );
                                                    Writer.WriteAttributeString( "value", AttributeValue.ToString() );
                                                }
                                                Writer.WriteEndElement();
                                            }
                                        }
                                        Writer.WriteEndElement();	// attvalues
                                    }
                                }
                                Writer.WriteEndElement();	// node
                            }
                        }
                        Writer.WriteEndElement();	// nodes

                        Writer.WriteStartElement( "edges" );
                        {
                            foreach( var GraphEdge in GraphEdges )
                            {
                                Writer.WriteStartElement( "edge" );
                                {
                                    Writer.WriteAttributeString( "id", GraphEdge.Id.ToString() );
                                    Writer.WriteAttributeString( "source", GraphEdge.Source.Id.ToString() );
                                    Writer.WriteAttributeString( "target", GraphEdge.Target.Id.ToString() );
                                    Writer.WriteAttributeString( "weight", GraphEdge.Weight.ToString() );

                                    Writer.WriteStartElement( "color", VizNamespace );
                                    {
                                        Writer.WriteAttributeString( "r", ((int)( GraphEdge.Color.R * 255.0f )).ToString() );
                                        Writer.WriteAttributeString( "g", ((int)( GraphEdge.Color.G * 255.0f )).ToString() );
                                        Writer.WriteAttributeString( "b", ((int)( GraphEdge.Color.B * 255.0f )).ToString() );
                                        Writer.WriteAttributeString( "a", GraphEdge.Color.A.ToString() );
                                    }
                                    Writer.WriteEndElement();	// viz:color

                                    Writer.WriteStartElement( "thickness", VizNamespace );
                                    {
                                        Writer.WriteAttributeString( "value", GraphEdge.Thickness.ToString() );
                                    }
                                    Writer.WriteEndElement();	// viz:thickness

                                    Writer.WriteStartElement( "shape", VizNamespace );
                                    {
                                        // NOTE: Valid shapes are:  solid, dotted, dashed, double
                                        Writer.WriteAttributeString( "value", "solid" );
                                    }
                                    Writer.WriteEndElement();	// viz:shape
                                }
                                Writer.WriteEndElement();	// edge
                            }
                        }
                        Writer.WriteEndElement();	// nodes
                    }

                    Writer.WriteEndElement();	// graph
                }
                Writer.WriteEndElement();	// gexf

                Writer.Flush();
            }
        }