#region Setup using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using ChartForgeX.Core; using ChartForgeX.Primitives; using ChartForgeX.Rendering; using ChartForgeX.Themes; using ChartForgeX.Topology; using ChartForgeX.Typography; using ChartForgeX.VisualArtifacts; using ChartForgeX.VisualBlocks; var mode = VisualThemeMode.Light; var theme = VisualTheme.Graphite(); var model = QuadrantRegionDepthRecipe.Create("interior-quadrants", mode); var context = new VisualRenderContext( new VisualLayoutOptions(new VisualSize(800, 440)), theme, mode, new VisualFrame("Processing time by workload", "", showLegend: null, showSurface: false)); var prepared = model.Prepare(context); File.WriteAllText("visual.svg", prepared.ToSvg()); File.WriteAllBytes("visual.png", prepared.ToPng()); File.WriteAllText("visual.html", prepared.ToArtifact("example", VisualArtifactKind.Chart).ToHtmlPage()); #endregion /// Effort/impact observations with native quadrant borders, deliberate captions and rules through an authored pivot. public static class QuadrantRegionDepthRecipe { /// Creates a complete public-API chart; exports use the same native prepared scene. public static Chart Create(string variant = "pivot-quadrants", VisualThemeMode mode = VisualThemeMode.Light) { if (variant is not ("pivot-quadrants" or "compact-pivot-quadrants" or "interior-quadrants" or "compact-interior-quadrants")) throw new ArgumentOutOfRangeException(nameof(variant)); var chart = Chart.Create().WithSize(variant.StartsWith("compact-", StringComparison.Ordinal) ? 360 : 800, 440) .WithTheme(VisualTheme.Graphite(), mode).WithTitle("Effort and impact").WithSubtitle("Authored 4-day / 6-point pivot") .WithLegend(false).WithDataLabels(false).WithGrid(false) .WithXAxis("Effort (days)").WithYAxis("Impact (score)").WithXAxisBounds(0, 10).WithYAxisBounds(0, 10) .AddScatter("Proposed work", new[] { new ChartPoint(1.4, 8.1), new ChartPoint(3.1, 7.3), new ChartPoint(7.2, 8.8), new ChartPoint(8.4, 6.8), new ChartPoint(2.5, 2.1), new ChartPoint(6.5, 3.2) }); if (variant.EndsWith("interior-quadrants", StringComparison.Ordinal)) chart.ConfigureXAxis(axis => axis.WithCrossAt(6)).ConfigureYAxis(axis => axis.WithCrossAt(4)); else chart.ConfigureXAxis(axis => axis.WithRuleCrossAt(6)).ConfigureYAxis(axis => axis.WithRuleCrossAt(4)); var border = new ChartStrokeStyle(width: 1.5, opacity: .65, dash: new[] { 5d, 3d }); chart.AddPlotRegion(new ChartPlotRegion(0, xMaximum: 4, yMinimum: 6, label: "Prioritize") .WithBorder(border).WithLabelPosition(ChartPlotRegionLabelPosition.TopLeft)) .AddPlotRegion(new ChartPlotRegion(1, xMinimum: 4, yMinimum: 6, label: "Plan") .WithBorder(border).WithLabelPosition(ChartPlotRegionLabelPosition.TopRight)) .AddPlotRegion(new ChartPlotRegion(2, xMaximum: 4, yMaximum: 6, label: "Consider") .WithBorder(border).WithLabelPosition(ChartPlotRegionLabelPosition.BottomLeft)) .AddPlotRegion(new ChartPlotRegion(3, xMinimum: 4, yMaximum: 6, label: "Reassess") .WithBorder(border).WithLabelPosition(ChartPlotRegionLabelPosition.BottomRight)); return chart; } }