# Tutorial 10: Rendering Workflow Diagrams This tutorial shows how to use the Stella Ops workflow rendering system to produce visual diagrams from workflow definitions. --- ## Prerequisites - A workflow canonical definition (from the compiler or imported JSON). - Reference to `StellaOps.Workflow.Renderer` and `StellaOps.ElkSharp` assemblies. --- ## Basic Usage ### 1. Create the Layout Engine ```csharp var engine = new ElkSharpWorkflowRenderLayoutEngine(); ``` ### 2. Configure Layout Options ```csharp var request = new WorkflowRenderLayoutRequest { Direction = WorkflowRenderLayoutDirection.LeftToRight, Effort = WorkflowRenderLayoutEffort.Best, NodeSpacing = 40, LayerSpacing = 60, }; ``` ### 3. Compute the Layout ```csharp var layout = await engine.LayoutAsync(graph, request); ``` The `graph` parameter is a `WorkflowRenderGraph` produced by the `WorkflowRenderGraphCompiler` from a canonical workflow definition. ### 4. Render to SVG ```csharp var svgRenderer = new WorkflowRenderSvgRenderer(); var svgDoc = svgRenderer.Render(layout, "My Workflow"); await File.WriteAllTextAsync("workflow.svg", svgDoc.Svg); ``` ### 5. Export to PNG ```csharp var pngExporter = new WorkflowRenderPngExporter(); await pngExporter.ExportAsync(svgDoc, "workflow.png", scale: 2f); ``` The `scale` parameter controls the pixel density (2f = 2x resolution for HiDPI). --- ## Layout Options Reference ### Direction | Value | Description | |-------|-------------| | `LeftToRight` | Nodes flow left to right (default for workflows). | | `TopToBottom` | Nodes flow top to bottom. Uses the legacy iterative path. | ### Effort Levels | Level | Speed | Quality | Use Case | |-------|-------|---------|----------| | `Draft` | Fast (~1s) | Basic | Interactive editing, previews | | `Balanced` | Medium (~3-5s) | Good | Medium graphs, dev-time rendering | | `Best` | Slow (~12-15s) | Production | Final artifacts, export, CI rendering | **Draft** uses 8 ordering iterations, 3 placement iterations, and baseline routing only. No iterative optimization is performed. **Balanced** uses 14 ordering iterations, 6 placement iterations, and light repair that fixes the worst violations without full A* search. **Best** uses 24 ordering iterations, 10 placement iterations, and the hybrid deterministic optimization pipeline with full-core parallel repair candidates. ### Spacing - **NodeSpacing** (default 40): Vertical gap between nodes in pixels. The engine may scale this up to 1.8x when edge density is high. - **LayerSpacing** (default 60): Horizontal gap between layers in pixels. --- ## Reading the Layout Result The `LayoutAsync` result contains positioned nodes and routed edges. ### Nodes ```csharp foreach (var node in layout.Nodes) { Console.WriteLine($"Node {node.Id}: ({node.X}, {node.Y}) " + $"size {node.Width}x{node.Height} " + $"shape={node.Shape}"); } ``` Node shapes include `Rectangle` (service tasks), `Diamond` (decision gateways), `Hexagon` (fork/join gateways), `Circle` (start/end events), and others. ### Edges ```csharp foreach (var edge in layout.Edges) { Console.WriteLine($"Edge {edge.SourceId} -> {edge.TargetId}"); foreach (var point in edge.BendPoints) { Console.WriteLine($" bend: ({point.X}, {point.Y})"); } } ``` Bend points define the orthogonal path from source to target. Two consecutive bend points with the same Y form a horizontal segment; two with the same X form a vertical segment. --- ## Diagnostics When using `Best` effort, the engine captures detailed diagnostics about the optimization process. ### Enabling Diagnostics Diagnostics are captured automatically in `Best` mode. Access them through the layout result. ### Violation Report The violation report lists each edge's violations with category, severity, and geometric details. ```csharp if (layout.Diagnostics?.ViolationReport != null) { foreach (var entry in layout.Diagnostics.ViolationReport) { Console.WriteLine($"Edge {entry.EdgeId}: " + $"{entry.Category} (penalty {entry.Penalty})"); } } ``` ### Violation Categories The scoring system uses 18 categories. Hard violations (100K penalty) include node crossings, under-node routing, shared lanes, and boundary slot conflicts. Medium violations (50K) include backtracking and detours. Soft violations (200-650) include edge crossings, proximity, and excessive bends. A FinalScore of 0 for hard violations indicates a clean layout with no visual defects. See the [Rendering Architecture](../../engine/16-elksharp-rendering-architecture.md) for the full violation taxonomy. ### Phase Timings ```csharp if (layout.Diagnostics?.PhaseTimings != null) { foreach (var phase in layout.Diagnostics.PhaseTimings) { Console.WriteLine($"{phase.Name}: {phase.Duration.TotalMilliseconds}ms"); } } ``` Phase timings cover ordering, placement, gutter expansion, base routing, iterative optimization, and post-processing. --- ## End-to-End Example ```csharp // Compile a workflow definition to a render graph var compiler = new WorkflowRenderGraphCompiler(); var graph = compiler.Compile(workflowDefinition); // Configure and run layout var engine = new ElkSharpWorkflowRenderLayoutEngine(); var request = new WorkflowRenderLayoutRequest { Direction = WorkflowRenderLayoutDirection.LeftToRight, Effort = WorkflowRenderLayoutEffort.Best, NodeSpacing = 40, LayerSpacing = 60, }; var layout = await engine.LayoutAsync(graph, request); // Render to SVG var svgRenderer = new WorkflowRenderSvgRenderer(); var svgDoc = svgRenderer.Render(layout, workflowDefinition.Name); await File.WriteAllTextAsync($"{workflowDefinition.Name}.svg", svgDoc.Svg); // Export to PNG at 2x resolution var pngExporter = new WorkflowRenderPngExporter(); await pngExporter.ExportAsync(svgDoc, $"{workflowDefinition.Name}.png", scale: 2f); // Check for violations var hardViolations = layout.Diagnostics?.ViolationReport? .Where(v => v.Penalty >= 100_000) .ToList(); if (hardViolations?.Any() == true) { Console.WriteLine($"WARNING: {hardViolations.Count} hard violations detected"); } ``` --- ## Further Reading - [ElkSharp Rendering Architecture](../../engine/16-elksharp-rendering-architecture.md) -- Full technical details of the Sugiyama pipeline, edge routing, and iterative optimization. - [Architectural Decisions](../../engine/17-elksharp-architectural-decisions.md) -- ADR records for key design choices. - [ENGINE.md](../../ENGINE.md) -- Workflow engine overview including layout engine configuration and render pipeline.