Anton 5 年 前
コミット
28a8166b51

+ 57 - 17
DrawGraph/Algorithm.cs

@@ -23,6 +23,12 @@ namespace DrawGraph
             return min_index;
         }
 
+        public static int DijkstraCount(Graph graph, int startIndex, int finishIndex)
+        {
+            var adj = Matrix.AdjacencyCreate(graph);
+            return DijkstraCount(adj, startIndex, finishIndex);
+        }
+
         public static int DijkstraCount(int[,] adjacencyMatrix, int startIndex, int finishIndex)
         {
             int n = adjacencyMatrix.GetLength(0);
@@ -56,32 +62,66 @@ namespace DrawGraph
 
             return path[finishIndex];
         }
-        
-        public static LinkedList<Node> DepthSearch(Node[] node, Edge[] edge, int sourceIndex, int targetIndex)
+
+        public static Node[] DepthSearch(Graph graph, int startIndex)
         {
-            var visited = new HashSet<Node>();
-            var path = new LinkedList<Node>();
-            Dfs(node[sourceIndex], node[targetIndex], visited, path, edge);
-            if (path.Count > 0)
-                path.AddFirst(node[sourceIndex]);
-            return path;
+            bool[] visitedBool = new bool[graph.Nodes.Length];
+            Node[] visited = new Node[graph.Nodes.Length];
+            visitedBool[startIndex] = true;
+            visited[startIndex] = new Node(graph.Nodes[startIndex].X, graph.Nodes[startIndex].Y);
+            var matrix = Matrix.AdjacencyCreate(graph.Nodes, graph.Edges);
+            for (int i = 0; i < graph.Nodes.Length; i++)
+            {
+                if (matrix[startIndex, i] != 0 && !visitedBool[i])
+                {
+                    DepthSeach(graph.Nodes, graph.Edges, i);
+                }
+            }
+            return visited;
         }
 
-        private static bool Dfs(Node node, Node goal,HashSet<Node> visited, LinkedList<Node> path, Edge[] edges)
+        public static Node[] DepthSeach(Node[] nodes, Edge[] edges, int startIndex)
         {
-            if (Node.Compare(node, goal))
-                return true;
+            bool[] visitedBool = new bool[nodes.Length]; 
+            Node[] visited = new Node[nodes.Length];
+            visitedBool[startIndex] = true;
+            visited[startIndex] = new Node(nodes[startIndex].X, nodes[startIndex].Y);
+            var matrix = Matrix.AdjacencyCreate(nodes, edges);
+            for(int i = 0; i < nodes.Length; i++)
+            {
+                if(matrix[startIndex, i]!=0 && !visitedBool[i])
+                {
+                    DepthSeach(nodes, edges, i);
+                }
+            }
+            return visited;
+        }
 
-            visited.Add(node);
-            foreach(var edge in edges.Where(x=>!visited.Contains(x.SourceNode) || !visited.Contains(x.TargetNode)))
+        // TODO
+        public static Node[] BreadthFirstSearch(Node[] nodes, Edge[] edges, int startIndex)
+        {
+            var visited = new HashSet<Node>();
+            var visitedBool = new bool[nodes.Length];
+            visited.Add(nodes[startIndex]);
+            var queue = new Queue<Node>();
+            queue.Enqueue(nodes[startIndex]);
+
+            while (queue.Count > 0)
             {
-                if(Dfs(edge.TargetNode, goal, visited, path, edges))
+                var current = queue.Dequeue();
+                bool HasAdj = false;
+                for(int i = 0; i < edges.Length; i++)
+                {
+                    if (Node.Compare(current, edges[i].SourceNode) || Node.Compare(current, edges[i].TargetNode))
+                        HasAdj = true;
+                }
+                if (HasAdj)
                 {
-                    path.AddFirst(edge.TargetNode);
-                    return true;
+                    return nodes;
                 }
+                return nodes;
             }
-            return false;
+            return nodes;
         }
     }
 }

+ 4 - 0
DrawGraph/DrawGraph.csproj

@@ -52,6 +52,7 @@
     <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
     </Reference>
+    <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Text.Encodings.Web, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
       <HintPath>..\packages\System.Text.Encodings.Web.4.6.0\lib\netstandard2.0\System.Text.Encodings.Web.dll</HintPath>
     </Reference>
@@ -64,6 +65,7 @@
     <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
       <HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
     </Reference>
+    <Reference Include="System.Web.Extensions" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -78,7 +80,9 @@
     <Compile Include="ArrowLineBase.cs" />
     <Compile Include="Edge.cs" />
     <Compile Include="Export.cs" />
+    <Compile Include="Graph.cs" />
     <Compile Include="GraphAction.cs" />
+    <Compile Include="GraphMLWriter.cs" />
     <Compile Include="Import.cs" />
     <Compile Include="Matrix.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

+ 33 - 14
DrawGraph/Edge.cs

@@ -1,8 +1,10 @@
 using System;
+using System.Runtime.Serialization;
 using System.Xml.Serialization;
 
 namespace DrawGraph
 {
+    [DataContract]
     public class Edge
     {
         [XmlAttribute("source")]
@@ -28,37 +30,35 @@ namespace DrawGraph
             this.IsFocused = IsFocused;
         }
 
-        public static double GetCenterByX(Edge edge)
+        public double GetCenterByX()
         {
-            var x = (edge.TargetNode.X + edge.SourceNode.X) / 2;
-            return x;
+            return (TargetNode.X + SourceNode.X) / 2;
         }
 
-        public static double GetCenterByY(Edge edge)
+        public double GetCenterByY()
         {
-            var y = (edge.TargetNode.Y + edge.SourceNode.Y) / 2;
-            return y;
+            return (TargetNode.Y + SourceNode.Y) / 2;
         }
 
         public static bool IsCursorOnNode(System.Windows.Point cursorPosition, Node Node)
         {
             try
             {
-                if (Node.CenterByX - cursorPosition.X <= Settings.NodeWidth / 2 &&
-                    Node.CenterByX - cursorPosition.X >= 0)
+                if (Node.GetCenterByX() - cursorPosition.X <= Settings.NodeWidth / 2 &&
+                    Node.GetCenterByX() - cursorPosition.X >= 0)
                 {
-                    if (Node.CenterByY - cursorPosition.Y <= Settings.NodeHeight / 2 &&
-                        Node.CenterByY - cursorPosition.Y >= 0)
+                    if (Node.GetCenterByY() - cursorPosition.Y <= Settings.NodeHeight / 2 &&
+                        Node.GetCenterByY() - cursorPosition.Y >= 0)
                     {
                         return true;
                     }
                 }
 
-                if (cursorPosition.X - Node.CenterByX <= Settings.NodeWidth / 2 &&
-                    cursorPosition.X - Node.CenterByX >= 0)
+                if (cursorPosition.X - Node.GetCenterByX() <= Settings.NodeWidth / 2 &&
+                    cursorPosition.X - Node.GetCenterByX() >= 0)
                 {
-                    if (cursorPosition.Y - Node.CenterByY <= Settings.NodeWidth / 2 &&
-                        cursorPosition.Y - Node.CenterByY >= 0)
+                    if (cursorPosition.Y - Node.GetCenterByY() <= Settings.NodeWidth / 2 &&
+                        cursorPosition.Y - Node.GetCenterByY() >= 0)
                     {
                         return true;
                     }
@@ -81,5 +81,24 @@ namespace DrawGraph
 
             return false;
         }
+
+        public static bool Compare(Edge edge1, Edge edge2)
+        {
+            if (Equals(edge1, edge2))
+                return true;
+            if (Node.Compare(edge1.SourceNode, edge2.SourceNode) && Node.Compare(edge1.TargetNode, edge2.TargetNode))
+                return true;
+            return false;
+        }
+
+        public static bool Exists(Edge[] edges, Edge edge)
+        {
+            foreach(var e in edges)
+            {
+                if (Compare(e, edge))
+                    return true;
+            }
+            return false;
+        }
     }
 }

+ 5 - 32
DrawGraph/Export.cs

@@ -7,6 +7,7 @@ using System.Xml;
 using System.Windows.Media.Imaging;
 using System.Text.Json;
 using System.Text;
+using System.Web.Script.Serialization;
 
 namespace DrawGraph
 {
@@ -144,44 +145,16 @@ namespace DrawGraph
             doc.Save(path);
         }
 
-        public static void ToJSON(
-            Node[] nodes, Edge[] edges, bool direction, string path)
+        public static void ToJSON(Node[] nodes, Edge[] edges, bool direction, string path)
         {
             if (edges is null)
             {
                 throw new ArgumentNullException(nameof(edges));
             }
 
-            JsonSerializerOptions options = new JsonSerializerOptions()
-            {
-                AllowTrailingCommas = true,
-                IgnoreNullValues = false,
-                PropertyNameCaseInsensitive = true
-            };
-            Type type = typeof(Node);
-            string[] json = new string[nodes.Length];
-            for(int i = 0; i < nodes.Length; i++)
-            {
-                json[i] = JsonSerializer.Serialize(nodes[i], type, options);
-                if (File.Exists(path))
-                {
-                    using(FileStream fs = new FileStream(path, FileMode.Append))
-                    {
-                        byte[] Byte = Encoding.ASCII.GetBytes(json[i]);
-                        fs.Write(Byte, 0, Byte.Length);
-                    }
-                }
-                else
-                {
-                    
-                    using(FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
-                    {
-                        path += "graph.json";
-                        byte[] Byte = Encoding.ASCII.GetBytes(json[i]);
-                        fs.Write(Byte, 0, Byte.Length);
-                    }
-                }
-            }
+            JavaScriptSerializer serializer = new JavaScriptSerializer();
+            var json = serializer.Serialize(nodes);
+            File.WriteAllText(path, json);
         }
     }
 }

+ 153 - 0
DrawGraph/Graph.cs

@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DrawGraph
+{
+    public class Graph
+    {
+        public Node[] Nodes;
+        public Edge[] Edges;
+        public string Name;
+        public bool Direction;
+
+        public Graph()
+        {
+            Nodes = new Node[0];
+            Edges = new Edge[0];
+            Name = "G";
+            Direction = false;
+        }
+
+        public Graph(Node[] nodes)
+        {
+            Nodes = nodes;
+            Name = "G";
+            Direction = false;
+        }
+
+        public Graph(Node[] nodes, Edge[] edges)
+        {
+            Nodes = nodes;
+            Edges = edges;
+            Name = "G";
+            Direction = false;
+        }
+
+        public Graph(Node[] nodes, Edge[] edges, string name)
+        {
+            Nodes = nodes;
+            Edges = edges;
+            Name = name;
+        }
+
+        public Graph(Node[] nodes, Edge[] edges, string name, bool isDirected)
+        {
+            Nodes = nodes;
+            Edges = edges;
+            Name = name;
+            Direction = isDirected;
+        }
+
+        public void SetGraphName(string name)
+        {
+            Name = name;
+        }
+
+        public void Add(Node node)
+        {
+            var length = Nodes.Length;
+            Array.Resize(ref Nodes, Nodes.Length + 1);
+            Nodes[length] = node;
+        }
+
+        public void AddRange(Node[] node)
+        {
+            var startLength = Nodes.Length;
+            Array.Resize(ref Nodes, Nodes.Length + node.Length);
+            var j = 0;
+            for(int i = startLength; i < Nodes.Length; i++)
+            {
+                Nodes[i] = node[j];
+                j++;
+            }
+        }
+
+        public void Add(Edge edge)
+        {
+            var length = Edges.Length;
+            Array.Resize(ref Edges, Edges.Length + 1);
+        }
+        
+        public void AddRange(Edge[] edge)
+        {
+            var startLength = Edges.Length;
+            Array.Resize(ref Edges, Edges.Length + edge.Length);
+            var j = 0;
+            for(int i = startLength; i < Edges.Length; i++)
+            {
+                Edges[i] = edge[j];
+                j++;
+            }
+        }
+
+        public void RemoveNode(int index)
+        {
+            Nodes = RemoveAt(Nodes, index);
+        }
+
+        public void RemoveNode(Node node)
+        {
+            for(int i = 0; i < Nodes.Length; i++)
+            {
+                if(Node.Compare(Nodes[i], node))
+                {
+                    Nodes = RemoveAt(Nodes, i);
+                    break;
+                }
+            }
+        }
+
+        public Node GetNode(int index)
+        {
+            return Nodes[index];
+        }
+
+
+        public Edge GetEdge(int index)
+        {
+            return Edges[index];
+        }
+
+        public void RemoveEdge(int index)
+        {
+            Nodes = RemoveAt(Nodes, index);
+        }
+
+        public void RemoveEdge(Edge edge)
+        {
+            for(int i = 0; i < Edges.Length; i++)
+            {
+                if(Edge.Compare(Edges[i], edge))
+                {
+                    Edges = RemoveAt(Edges, i);
+                    break;
+                }
+            }
+        }
+
+        private T[] RemoveAt<T>(T[] source, int index)
+        {
+            T[] dest = new T[source.Length - 1];
+            if (index > 0)
+                Array.Copy(source, 0, dest, 0, index);
+
+            if (index < source.Length - 1)
+                Array.Copy(source, index + 1, dest, index, source.Length - index - 1);
+
+            return dest;
+        }
+    }
+}

+ 127 - 0
DrawGraph/GraphAction.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Windows.Controls;
+using System.Windows.Shapes;
+
+namespace DrawGraph
+{
+    class GraphAction
+    {
+        public static void ClearCanvas(Edge[] edges, Node[] nodes)
+        {
+            if (edges != null && nodes != null)
+            {
+                Array.Clear(edges, 0, edges.Length);
+                Array.Clear(nodes, 0, nodes.Length);
+            }
+            else
+            {
+                throw new NullReferenceException();
+            }
+        }
+
+        public static void ClearCanvas(Graph graph)
+        {
+            ClearCanvas(graph.Edges, graph.Nodes);
+        }
+
+        public static void RemoveAllEdgesFromCanvas(Canvas canvas, Line[] lines, Edge[] edges)
+        {
+            Array.Clear(edges, 0, edges.Length);
+            for (int i = 0; i < lines.Length; i++)
+            {
+                canvas.Children.Remove(lines[i]);
+            }
+        }
+
+        public static void RemoveLastAddedFromCanvas(Canvas canvas)
+        {
+            int removingElement = canvas.Children.Count - 1;
+            canvas.Children.RemoveAt(removingElement);
+        }
+
+        public Line GetEdgeProperties(Edge edge)
+        {
+            Line line = new Line
+            {
+                X1 = edge.SourceNode.X,
+                Y1 = edge.SourceNode.Y,
+                X2 = edge.TargetNode.X,
+                Y2 = edge.TargetNode.Y,
+                Stroke = Settings.FillColor,
+                StrokeThickness = Settings.StrokeThickness
+            };
+            return line;
+        }
+
+        public Ellipse GetEllipseProperties(Node node)
+        {
+            Ellipse ellipse = new Ellipse
+            {
+                Fill = Settings.FillColor,
+                Width = Settings.NodeWidth,
+                Height = Settings.NodeHeight
+            };
+            Canvas.SetLeft(ellipse, node.X);
+            Canvas.SetTop(ellipse, node.Y);
+            return ellipse;
+        }
+
+        public static void AddGraphToCanvas(Graph graph, Canvas canvas)
+        {
+            AddRangeToCanvas(graph.Nodes, graph.Edges, canvas);
+        }
+
+        public static void AddRangeToCanvas(Node[] nodes, Edge[] edges, Canvas canvas)
+        {
+            Ellipse[] ellipses = new Ellipse[nodes.Length];
+            Line[] lines = new Line[edges.Length];
+            ArrowLine[] arrowLines = new ArrowLine[edges.Length];
+
+            for (int i = 0; i < nodes.Length; i++)
+            {
+                ellipses[i] = new Ellipse()
+                {
+                    Fill = Settings.FillColor,
+                    Width = Settings.NodeWidth,
+                    Height = Settings.NodeHeight
+                };
+                Canvas.SetLeft(ellipses[i], nodes[i].X);
+                Canvas.SetTop(ellipses[i], nodes[i].Y);
+                canvas.Children.Add(ellipses[i]);
+            }
+
+            for (int i = 0; i < edges.Length; i++)
+            {
+                var edge = edges[i];
+                if (edge.IsFocused)
+                {
+                    arrowLines[i] = new ArrowLine()
+                    {
+                        X1 = edge.SourceNode.GetCenterByX(),
+                        Y1 = edge.SourceNode.GetCenterByY(),
+                        X2 = edge.TargetNode.GetCenterByX(),
+                        Y2 = edge.TargetNode.GetCenterByY(),
+                        Stroke = Settings.FillColor,
+                        Fill = Settings.FillColor,
+                        StrokeThickness = Settings.StrokeThickness
+                    };
+                    canvas.Children.Add(arrowLines[i]);
+                }
+                else
+                {
+                    lines[i] = new Line()
+                    {
+                        X1 = edge.SourceNode.GetCenterByX(),
+                        Y1 = edge.SourceNode.GetCenterByY(),
+                        X2 = edge.TargetNode.GetCenterByX(),
+                        Y2 = edge.TargetNode.GetCenterByY(),
+                        Stroke = Settings.FillColor,
+                        Fill = Settings.FillColor,
+                        StrokeThickness = Settings.StrokeThickness
+                    };
+                    canvas.Children.Add(lines[i]);
+                }
+            }
+        }
+    }
+}

+ 109 - 0
DrawGraph/GraphMLWriter.cs

@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace DrawGraph
+{
+    public class GraphMLWriter
+    {
+        public static void WriteEdges(string path, Edge[] edges, bool direction)
+        {
+            //XmlDocument doc = new XmlDocument();
+            //XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
+            //var root = doc.CreateElement("graph");
+            //var attr = doc.CreateAttribute("id");
+            //attr.InnerText = "G";
+            //root.Attributes.Append(attr);
+            //var dir = doc.CreateAttribute("edgedefault");
+            //dir.InnerText = direction ? "directed" : "undirected";
+            //root.Attributes.Append(dir);
+            //doc.AppendChild(declaration);
+            //doc.AppendChild(root);
+            //XmlProcessingInstruction pi =
+            //    doc.CreateProcessingInstruction("graphml", "xmlns=\"http://graphml.graphdrawing.org/xmlns \" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance \" xsi: schemaLocation = \"http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd \"");
+            //doc.InsertBefore(pi, doc.ChildNodes[1]);
+
+            //for (int i = 0; i < edges.Length; i++)
+            //{
+            //    XmlNode edge = doc.CreateElement("edge");
+            //    var sourceAttribute = doc.CreateAttribute("source");
+            //    for (int j = 0; j < nodes.Length; j++)
+            //        if (Node.Compare(edges[i].SourceNode, nodes[j]))
+            //            sourceAttribute.InnerText = "n" + j.ToString();
+            //    edge.Attributes.Append(sourceAttribute);
+            //    var targetAttribute = doc.CreateAttribute("target");
+            //    for (int j = 0; j < nodes.Length; j++)
+            //        if (Node.Compare(edges[i].TargetNode, nodes[j]))
+            //            targetAttribute.InnerText = "n" + j.ToString();
+            //    edge.Attributes.Append(targetAttribute);
+            //    if (edges[i].Weight > 0)
+            //    {
+            //        var weightAttr = doc.CreateAttribute("weight");
+            //        weightAttr.InnerText = edges[i].Weight.ToString();
+            //        edge.Attributes.Append(weightAttr);
+            //    }
+            //    root.AppendChild(edge);
+            //}
+            //doc.Save(path);
+        }
+
+        public static void WriteAllGraph(string path, Node[] nodes, Edge[] edges, bool direction)
+        {
+            XmlDocument doc = new XmlDocument();
+            XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
+            var root = doc.CreateElement("graph");
+            var attr = doc.CreateAttribute("id");
+            attr.InnerText = "G";
+            root.Attributes.Append(attr);
+            var dir = doc.CreateAttribute("edgedefault");
+            dir.InnerText = direction ? "directed" : "undirected";
+            root.Attributes.Append(dir);
+            doc.AppendChild(declaration);
+            doc.AppendChild(root);
+            XmlProcessingInstruction pi =
+                doc.CreateProcessingInstruction("graphml", "xmlns=\"http://graphml.graphdrawing.org/xmlns \" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance \" xsi: schemaLocation = \"http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd \"");
+            doc.InsertBefore(pi, doc.ChildNodes[1]);
+
+            for (int i = 0; i < nodes.Length; i++)
+            {
+                XmlNode node = doc.CreateElement("node");
+                var attribute = doc.CreateAttribute("id");
+                attribute.InnerText = "n" + i.ToString();
+                node.Attributes.Append(attribute);
+                var XCoord = doc.CreateAttribute("positionX");
+                XCoord.InnerText = nodes[i].X.ToString();
+                node.Attributes.Append(XCoord);
+                var YCoord = doc.CreateAttribute("positionY");
+                YCoord.InnerText = nodes[i].Y.ToString();
+                node.Attributes.Append(YCoord);
+                root.AppendChild(node);
+            }
+
+            for (int i = 0; i < edges.Length; i++)
+            {
+                XmlNode edge = doc.CreateElement("edge");
+                var sourceAttribute = doc.CreateAttribute("source");
+                for (int j = 0; j < nodes.Length; j++)
+                    if (Node.Compare(edges[i].SourceNode, nodes[j]))
+                        sourceAttribute.InnerText = "n" + j.ToString();
+                edge.Attributes.Append(sourceAttribute);
+                var targetAttribute = doc.CreateAttribute("target");
+                for (int j = 0; j < nodes.Length; j++)
+                    if (Node.Compare(edges[i].TargetNode, nodes[j]))
+                        targetAttribute.InnerText = "n" + j.ToString();
+                edge.Attributes.Append(targetAttribute);
+                if (edges[i].Weight > 0)
+                {
+                    var weightAttr = doc.CreateAttribute("weight");
+                    weightAttr.InnerText = edges[i].Weight.ToString();
+                    edge.Attributes.Append(weightAttr);
+                }
+                root.AppendChild(edge);
+            }
+            doc.Save(path);
+        }
+    }
+}

+ 98 - 0
DrawGraph/Import.cs

@@ -0,0 +1,98 @@
+using System.IO;
+using System.Windows.Controls;
+using System.Windows.Shapes;
+using System.Xml.Serialization;
+
+namespace DrawGraph
+{
+    public class Import
+    {
+        public static Node[] NodesFromGraphML(string path)
+        {
+            if (File.Exists(path))
+            {
+                XmlSerializer xml = new XmlSerializer(typeof(Node));
+                string xmlString = File.ReadAllText(path);
+                Node[] nodes;
+                using(TextReader reader = new StringReader(xmlString))
+                {
+                    nodes = (Node[])xml.Deserialize(reader);
+                }
+                return nodes;
+            }
+            else
+            {
+                throw new FileNotFoundException("File not found: " + path);
+            }
+        }
+
+        public static Edge[] EdgesFromGraphML(string path)
+        {
+            if (File.Exists(path))
+            {
+                XmlSerializer xml = new XmlSerializer(typeof(Edge));
+                string xmlString = File.ReadAllText(path);
+                Edge[] edges;
+                using (TextReader reader = new StringReader(xmlString))
+                    edges = (Edge[])xml.Deserialize(reader);
+                return edges;
+            }
+            else
+            {
+                throw new FileNotFoundException("File not found: " + path);
+            }
+        }
+
+        public static void GraphMLToCanvas(string path, Canvas canvas)
+        {
+            Node[] nodes = NodesFromGraphML(path);
+            Edge[] edges = EdgesFromGraphML(path);
+
+            Ellipse[] ellipses = new Ellipse[nodes.Length];
+            Line[] lines = new Line[edges.Length];
+            ArrowLine[] arrowLines = new ArrowLine[edges.Length];
+            for(int i = 0; i < nodes.Length; i++)
+            {
+                ellipses[i] = new Ellipse()
+                {
+                    Fill = Settings.FillColor,
+                    Width = Settings.NodeWidth,
+                    Height = Settings.NodeHeight
+                };
+                Canvas.SetLeft(ellipses[i], nodes[i].X);
+                Canvas.SetTop(ellipses[i], nodes[i].Y);
+                canvas.Children.Add(ellipses[i]);
+            }
+
+            for(int i = 0; i < edges.Length; i++)
+            {
+                if (edges[i].IsFocused)
+                {
+                    arrowLines[i] = new ArrowLine()
+                    {
+                        Stroke = Settings.FillColor,
+                        StrokeThickness = Settings.StrokeThickness,
+                        X1 = edges[i].SourceNode.GetCenterByX(),
+                        X2 = edges[i].TargetNode.GetCenterByX(),
+                        Y1 = edges[i].SourceNode.GetCenterByY(),
+                        Y2 = edges[i].TargetNode.GetCenterByY()
+                    };
+                    canvas.Children.Add(arrowLines[i]);
+                }
+                else
+                {
+                    lines[i] = new Line()
+                    {
+                        Stroke = Settings.FillColor,
+                        StrokeThickness = Settings.StrokeThickness,
+                        X1 = edges[i].SourceNode.GetCenterByX(),
+                        X2 = edges[i].TargetNode.GetCenterByX(),
+                        Y1 = edges[i].SourceNode.GetCenterByY(),
+                        Y2 = edges[i].TargetNode.GetCenterByY()
+                    };
+                    canvas.Children.Add(lines[i]);
+                }
+            }
+        }
+    }
+}

+ 52 - 12
DrawGraph/Matrix.cs

@@ -79,6 +79,15 @@ namespace DrawGraph
             return matrix;
         }
         /// <summary>
+        /// Creates an adjacency matrix from given graph
+        /// </summary>
+        /// <param name="graph">Your graph</param>
+        /// <returns>Adjacency matrix in 2D int array</returns>
+        public static int[,] AdjacencyCreate(Graph graph)
+        {
+            return AdjacencyCreate(graph.Nodes, graph.Edges);
+        }
+        /// <summary>
         /// Creates an adjacency matrix from given nodes and edges
         /// </summary>
         /// <param name="nodes">List of nodes</param>
@@ -135,6 +144,15 @@ namespace DrawGraph
             return matrix;
         }
         /// <summary>
+        /// Creates an incidence matrix from given graph
+        /// </summary>
+        /// <param name="graph">Your graph</param>
+        /// <returns>Incidence matrix in 2D int array</returns>
+        public static int[,] IncidenceCreate(Graph graph)
+        {
+            return IncidenceCreate(graph.Nodes, graph.Edges);
+        }
+        /// <summary>
         /// Creates an incidence matrix from given nodes and edges
         /// </summary>
         /// <param name="nodes">List of nodes</param>
@@ -152,7 +170,7 @@ namespace DrawGraph
         /// </summary>
         /// <param name="matrix">Adjacency matrix</param>
         /// <returns>Tuple of node and edge array</returns>
-        public static Tuple<Node[], Edge[]> FromAdjacency(int[,] matrix)
+        public static Graph FromAdjacency(int[,] matrix)
         {
             Random random = new Random();
             Node[] nodes = new Node[matrix.GetLength(0)];
@@ -200,7 +218,8 @@ namespace DrawGraph
                     }
                 }
             }
-            return Tuple.Create(nodes, edges);
+            Graph graph = new Graph(nodes, edges);
+            return graph;
         }
         /// <summary>
         /// Creates nodes and edges from adjacency matrix and add all elements to your canvas
@@ -208,21 +227,21 @@ namespace DrawGraph
         /// <param name="matrix">Adjacency matrix</param>
         /// <param name="canvas">Canvas to draw</param>
         /// <returns>Tuple of nodes and edges</returns>
-        public static Tuple<Node[], Edge[]> FromAdjacencyToCanvas(int[,] matrix, Canvas canvas)
+        public static Graph FromAdjacencyToCanvas(int[,] matrix, Canvas canvas)
         {
             var items = FromAdjacency(matrix);
-            Node[] nodes = items.Item1;
-            Edge[] edges = items.Item2;
+            Node[] nodes = items.Nodes;
+            Edge[] edges = items.Edges;
 
             GraphAction.AddRangeToCanvas(nodes, edges, canvas);
-            return Tuple.Create(nodes, edges);
+            return items;
         }
         /// <summary>
         /// Creates nodes and edges from incidence matrix
         /// </summary>
         /// <param name="matrix">Incidence matrix</param>
         /// <returns>Tuple of nodes and edges array</returns>
-        public static Tuple<Node[], Edge[]> FromIncidence(int[,] matrix)
+        public static Graph FromIncidence(int[,] matrix)
         {
             Random random = new Random();
             int rows = matrix.GetLength(0);
@@ -258,7 +277,8 @@ namespace DrawGraph
                     }
                 }
             }
-            return Tuple.Create(nodes, edges);
+            Graph graph = new Graph(nodes, edges);
+            return graph;
         }
         /// <summary>
         /// Creates nodes and edges from incidence matrix and add all elements to your canvas
@@ -266,13 +286,33 @@ namespace DrawGraph
         /// <param name="matrix">Incidence matrix</param>
         /// <param name="canvas">Canvas to draw</param>
         /// <returns>Tuple of nodes and edges</returns>
-        public static Tuple<Node[], Edge[]> FromIncidenceToCanvas(int[,] matrix, Canvas canvas)
+        public static Graph FromIncidenceToCanvas(int[,] matrix, Canvas canvas)
         {
             var tuple = FromIncidence(matrix);
-            Node[] nodes = tuple.Item1;
-            Edge[] edges = tuple.Item2;
+            Node[] nodes = tuple.Nodes;
+            Edge[] edges = tuple.Edges;
             GraphAction.AddRangeToCanvas(nodes, edges, canvas);
-            return Tuple.Create(nodes, edges);
+            return tuple;
+        }
+
+        //TODO
+        public static int[,] DistanceCreate(Node[] nodes, Edge[] edges)
+        {
+            if (edges is null)
+            {
+                throw new ArgumentNullException(nameof(edges));
+            }
+
+            var length = nodes.Length;
+            int[,] matrix = new int[length, length];
+            
+
+            return matrix;
+        }
+
+        public static int[,] DistanceCreate(Graph graph)
+        {
+            return DistanceCreate(graph.Nodes, graph.Edges);
         }
     }
 }

+ 42 - 4
DrawGraph/Node.cs

@@ -2,6 +2,8 @@
 using System.Windows.Shapes;
 using System.Windows.Controls;
 using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System;
 
 namespace DrawGraph
 {
@@ -19,14 +21,28 @@ namespace DrawGraph
         }
 
         /// <summary>
-        /// Get center X-coordinate of node
+        /// Identifier of node (numeric)
+        /// Returns identifier "NXX"
+        /// Where XX - established numeric value
         /// </summary>
-        public int CenterByX => (X * 2 + (Settings.NodeWidth/2)) / 2;
 
         /// <summary>
-        /// Get center Y-coordinate of node
+        /// Get center of node by X-coordinate
         /// </summary>
-        public int CenterByY => (Y * 2 + (Settings.NodeHeight / 2)) / 2;
+        /// <returns>Center of node by X</returns>
+        public int GetCenterByX()
+        {
+            return (X * 2 + (Settings.NodeWidth / 2)) / 2;
+        }
+
+        /// <summary>
+        /// Get center of node by Y-coordinate
+        /// </summary>
+        /// <returns>Center of node by Y</returns>
+        public int GetCenterByY()
+        {
+            return (Y * 2 + (Settings.NodeHeight / 2)) / 2;
+        }
 
         /// <summary>
         /// Compare two nodes
@@ -66,5 +82,27 @@ namespace DrawGraph
                     return true;
             return false;
         }
+
+
+        /// <summary>
+        /// Check if node has neighbors
+        /// </summary>
+        /// <param name="node">Node to check</param>
+        /// <param name="edges">Edges array</param>
+        /// <returns></returns>
+        public static bool HasNeighbors(Node node, Edge[] edges)
+        {
+            foreach(var edge in edges)
+            {
+                if (Compare(node, edge.SourceNode) || Compare(node, edge.TargetNode))
+                    return true;
+            }
+            return false;
+        }
+        public static bool HasNeighbors(Node node, List<Edge> edges)
+        {
+            var a = edges.ToArray();
+            return HasNeighbors(node, a);
+        }
     }
 }

+ 7 - 5
DrawGraph/Properties/AssemblyInfo.cs

@@ -1,4 +1,5 @@
-using System.Reflection;
+using System.Resources;
+using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
@@ -6,9 +7,9 @@ using System.Runtime.InteropServices;
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 [assembly: AssemblyTitle("DrawGraph")]
-[assembly: AssemblyDescription("")]
+[assembly: AssemblyDescription("Simple way to use graphs in C#")]
 [assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
+[assembly: AssemblyCompany("DrawGraph")]
 [assembly: AssemblyProduct("DrawGraph")]
 [assembly: AssemblyCopyright("Copyright ©  2019")]
 [assembly: AssemblyTrademark("")]
@@ -32,5 +33,6 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("0.0.2.2")]
+[assembly: AssemblyFileVersion("0.0.2.2")]
+[assembly: NeutralResourcesLanguage("en")]

+ 23 - 0
DrawGraph/app.config

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+      </dependentAssembly>
+      <dependentAssembly>
+        <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>

+ 12 - 0
DrawGraph/packages.config

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Microsoft.Bcl.AsyncInterfaces" version="1.0.0" targetFramework="net472" />
+  <package id="System.Buffers" version="4.5.0" targetFramework="net472" />
+  <package id="System.Memory" version="4.5.3" targetFramework="net472" />
+  <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
+  <package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0" targetFramework="net472" />
+  <package id="System.Text.Encodings.Web" version="4.6.0" targetFramework="net472" />
+  <package id="System.Text.Json" version="4.6.0" targetFramework="net472" />
+  <package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net472" />
+  <package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
+</packages>