Mostlylucid.Dagre
2.0.1
dotnet add package Mostlylucid.Dagre --version 2.0.1
NuGet\Install-Package Mostlylucid.Dagre -Version 2.0.1
<PackageReference Include="Mostlylucid.Dagre" Version="2.0.1" />
<PackageVersion Include="Mostlylucid.Dagre" Version="2.0.1" />
<PackageReference Include="Mostlylucid.Dagre" />
paket add Mostlylucid.Dagre --version 2.0.1
#r "nuget: Mostlylucid.Dagre, 2.0.1"
#:package Mostlylucid.Dagre@2.0.1
#addin nuget:?package=Mostlylucid.Dagre&version=2.0.1
#tool nuget:?package=Mostlylucid.Dagre&version=2.0.1
Mostlylucid.Dagre
A modern, high-performance C# graph layout engine implementing the Sugiyama (layered) algorithm. This is an extensively modernized fork of Dagre.NET (itself a port of dagre.js).
Why fork? The original Dagre.NET was a faithful line-by-line port of dagre.js, inheriting JavaScript idioms like
dynamicproperty bags andobject[]arrays. This made it slow, allocation-heavy, and incompatible with modern .NET features like NativeAOT and WebAssembly. Mostlylucid.Dagre rewrites the internals for idiomatic, high-performance .NET while preserving the same Sugiyama layout algorithm.
Features
- Zero
dynamic— all property bags replaced with strongly-typedNodeLabel,EdgeLabel,GraphLabelclasses - Zero boxing — no
Dictionary<string, object>, noobject[]parameter arrays - AOT-compatible — no
Microsoft.CSharpdependency, works with NativeAOT and Blazor WASM - Multi-target —
net6.0,net8.0,net10.0 - 4-8x faster than original Dagre.NET with 5-11x less memory (see benchmarks below)
- Compound graph support — nested subgraphs with automatic boundary layout
- High-level and low-level APIs — simple
DagreInputGraphfor quick use, fullDagreGraphfor advanced control
Install
dotnet add package Mostlylucid.Dagre
Usage
High-Level API
using Dagre;
var graph = new DagreInputGraph();
var a = graph.AddNode(tag: "Start", width: 100, height: 40);
var b = graph.AddNode(tag: "Process", width: 120, height: 40);
var c = graph.AddNode(tag: "End", width: 100, height: 40);
graph.AddEdge(a, b);
graph.AddEdge(b, c);
graph.Layout();
// Nodes now have X, Y coordinates
Console.WriteLine($"{a.Tag}: ({a.X}, {a.Y})");
Console.WriteLine($"{b.Tag}: ({b.X}, {b.Y})");
Console.WriteLine($"{c.Tag}: ({c.X}, {c.Y})");
Low-Level API
For full control over the layout graph:
using Dagre;
var g = new DagreGraph { IsDirected = true, IsCompound = false, IsMultigraph = false };
g.SetGraphLabel(new GraphLabel
{
RankDir = "TB",
NodeSep = 50,
RankSep = 50,
EdgeSep = 10,
Ranker = "network-simplex"
});
g.SetNode("a", new NodeLabel { Width = 100, Height = 40 });
g.SetNode("b", new NodeLabel { Width = 120, Height = 40 });
g.SetEdge("a", "b", new EdgeLabel { Weight = 1, Minlen = 1 });
DagreLayout.runLayout(g);
var aLabel = g.Node("a");
Console.WriteLine($"a: ({aLabel.X}, {aLabel.Y})");
Layout Options
| Option | Type | Default | Description |
|---|---|---|---|
RankDir |
string |
"TB" |
Layout direction: TB, BT, LR, RL |
RankSep |
double |
50 |
Pixels between ranks (layers) |
NodeSep |
double |
50 |
Pixels between nodes in same rank |
EdgeSep |
double |
10 |
Pixels between edges |
Align |
string |
null |
Node alignment: UL, UR, DL, DR |
Ranker |
string |
"network-simplex" |
Ranking algorithm: network-simplex, tight-tree, longest-path |
Acyclicer |
string |
null |
Set to "greedy" to break cycles |
Compound Graphs
var g = new DagreGraph { IsDirected = true, IsCompound = true };
g.SetGraphLabel(new GraphLabel { RankDir = "TB" });
g.SetNode("group", new NodeLabel());
g.SetNode("a", new NodeLabel { Width = 80, Height = 40 });
g.SetNode("b", new NodeLabel { Width = 80, Height = 40 });
g.SetParent("a", "group");
g.SetParent("b", "group");
g.SetEdge("a", "b", new EdgeLabel());
DagreLayout.runLayout(g);
Performance
Compared to the original Dagre.NET 1.0.0.6 NuGet package, using identical graph construction with BenchmarkDotNet on .NET 10:
| Graph Size | Original Dagre.NET | Mostlylucid.Dagre | Speedup | Memory Reduction |
|---|---|---|---|---|
| 5 nodes, 8 edges | 1.2 ms / 3.2 MB | 0.3 ms / 0.7 MB | 4x | 4.6x |
| 20 nodes, 30 edges | 14.8 ms / 24 MB | 1.8 ms / 4.0 MB | 8x | 6x |
| 50 nodes, 80 edges | 140 ms / 136 MB | 17 ms / 24 MB | 8x | 5.6x |
| 200 nodes, 350 edges | 4,127 ms / 3.5 GB | 564 ms / 321 MB | 7x | 11x |
The improvements come from eliminating dynamic dispatch, removing boxing allocations, and using strongly-typed data
structures throughout the pipeline.
Architecture
The layout pipeline follows the Sugiyama method:
- Acyclic — reverse edges to eliminate cycles
- Rank — assign layers via network simplex
- Order — minimize edge crossings within layers
- Coordinate Assignment — Brandes-Kopf algorithm for X coordinates
- Normalize/Denormalize — insert and remove dummy nodes for long edges
- Edge Routing — compute control points for spline edges
Credits
- dagre — original JavaScript implementation by Chris Pettitt
- Dagre.NET — original C# port by fel88
- Naiad — Mermaid-to-SVG library that uses this layout engine
License
MIT — original license from fel88's Dagre.NET port.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Mostlylucid.Dagre:
| Package | Downloads |
|---|---|
|
Mostlylucid.Naiad
Pure C# Mermaid-compatible diagram renderer. 30+ diagram types, SVG output, no JavaScript required. |
|
|
WpfMarkdownViewer.Mermaid
Pure-.NET Mermaid diagram rendering plugin for WpfMarkdownViewer. |
GitHub repositories
This package is not used by any popular GitHub repositories.