public override void Save(TextWriter writer, IGraph graph) { if (!graph.IsDirected) { throw new InvalidGraphFormatException("graph must be directed"); } var rootVertices = graph.Vertices.ToArray(); try { foreach (var column in graph.ToAdjList()) { var parent = column.Key; foreach (var child in column.Value) { rootVertices[child.Index - 1] = null; } } } catch (IndexOutOfRangeException e) { throw new ArgumentException($"graph must contains all vertices between 1 and {graph.Vertices.Max(x => x.Index)}", e); } rootVertices = rootVertices.Where(x => x != null).ToArray(); if (rootVertices.Length == 0) { throw new InvalidGraphFormatException("graph must have some vertices without parent"); } var rtfWriter = new RtfWriter(writer); rtfWriter.WriteDocumentStart(); var stack = new Stack <Tuple <IVertex, int> >(); int indent = -1; var dfs = new Algorithms.Helpers.DepthFirstSearch(graph) { ProcessVertexEarly = (_) => { indent++; }, ProcessVertexLate = (v) => { stack.Push(new Tuple <IVertex, int>(v, indent)); indent--; } }; foreach (var root in rootVertices) { dfs.Run(root); while (stack.Count > 0) { var col = stack.Pop(); var vertex = col.Item1; var indentLevel = col.Item2; rtfWriter.WriteLine(vertex.Name, indentLevel, vertex.Color.ToString()); } } rtfWriter.WriteDocumentEnd(); }