beto-rodriguez / LiveCharts2

Simple, flexible, interactive & powerful charts, maps and gauges for .Net, LiveCharts2 can now practically run everywhere Maui, Uno Platform, Blazor-wasm, WPF, WinForms, Xamarin, Avalonia, WinUI, UWP.
https://livecharts.dev
MIT License
4.42k stars 576 forks source link

Option for equally sized axes in CartesianChart #1351

Open mrericrichter opened 1 year ago

mrericrichter commented 1 year ago

When showing a Cartesian chart of x and y values, I would like to have the option to set the same axis-to-screen ratio for both axes x and y. This is especially required if data contains physical extensions such as the width and length of an object. If the axes are not equally sized, these objects get distorted.

Example with differently sized axes and with distorted object extensions (the red rectangle should be extended to the right): image

Example with equally sized axes and correct object extensions: image

Current workaround: Derive from CartesianChart, register to the 'Measuring' event, and reset one of the axes:

public class CartesianChartAxisEqual : CartesianChart
{
    public CartesianChartAxisEqual()
    {
        Measuring += context => 
        {
            var xAxis = XAxes.First();
            var yAxis = YAxes.First();

            var axisLengthXPixels = context.ControlSize.Width;
            var axisLengthYPixels = context.ControlSize.Height;

            // (ymax - ymin) / (xmax - xmin) = axisLengthYPixels / axisLengthXPixels
            var newYMaxLimit = axisLengthYPixels/ axisLengthXPixels * (xAxis.MaxLimit - xAxis.MinLimit) + yAxis.MinLimit;
            var yMaxLimitDiff = newYMaxLimit - yAxis.MaxLimit;
            var yMaxLimitDelta = yMaxLimitDiff / 2;
            yAxis.MaxLimit += yMaxLimitDelta;
            yAxis.MinLimit -= yMaxLimitDelta; 
        };
    }
}

As a reference, there are such options in other chart APIs, e.g. 'axes equal' in Matlab, or 'PlotType = PlotType.Cartesian' in oxyplot.

mrericrichter commented 1 year ago

There might be several ways to auto-resize one of the axes (and which one), so adding an example to the docs might be a good idea.