Code/Core/Graph.GraphViz.cs
using System.IO;
using System.Threading.Tasks;
using Nodebox.Dependencies.DotNetGraph.Compilation;
using Nodebox.Dependencies.DotNetGraph.Core;
using Nodebox.Dependencies.DotNetGraph.Extensions;
namespace Nodebox.GraphViz;
public static partial class GraphExtensions {
extension(Graph graph) {
public DotGraph ToGraphViz(string identifier = null) {
identifier ??= graph.GraphVizIdentifier;
identifier ??= "G";
var identifierDisjunctor = new IdentifierDisjunctor();
var dot = new DotGraph().WithIdentifier(identifier).Directed();
dot.RankDir = "LR";
var pinDotNodeStore = new Dictionary<(Node, Flow, PinIndex), DotNode>();
foreach (var node in graph.GetAll<Node>()) {
if (node.IsValid()) {
var subgraph = node.ToGraphVizSubGraph(pinDotNodeStore, identifierDisjunctor);
dot.Add(subgraph);
}
}
foreach (var wire in graph.GetAll<Wire>()) {
if (!wire.IsValid()) { continue; }
if (!pinDotNodeStore.ContainsKey((wire.Source, Flow.Output, wire.SourceIndex))) { continue; }
if (!pinDotNodeStore.ContainsKey((wire.Destination, Flow.Input, wire.DestinationIndex))) { continue; }
var source = pinDotNodeStore[(wire.Source, Flow.Output, wire.SourceIndex)];
var destination = pinDotNodeStore[(wire.Destination, Flow.Input, wire.DestinationIndex)];
var edge = new DotEdge()
.Source(source)
.Destination(destination);
dot.Add(edge);
}
return dot;
}
public async Task<string> ToGraphVizStringAsync(string name = "G") {
var dot = graph.ToGraphViz();
using var writer = new StringWriter();
var context = new CompilationContext(writer, new());
await dot.CompileAsync(context);
var result = writer.GetStringBuilder().ToString();
return result;
}
public string ToGraphVizString(string name = "G") => graph.ToGraphVizStringAsync(name).GetAwaiter().GetResult();
}
}
public static partial class GraphExtensions {
extension(Graph graph) {
public string GraphVizIdentifier {
get => graph.GetMetaOrDefault<string>("GraphVizName", null);
set => graph.SetMeta("GraphVizName", value);
}
}
}