Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Affine transformations in Oxyplot

I would like to perform a simple affine transformation to a LineSeries

Unfortunately I cannot simply do this:

foreach (var point in myLineSeries.Points)
{
    point.X = point.X * Math.Cos(angle_rad) + point.Y ...
    point.Y = ...
}

...as the properties X and Y of a DataPoint do not have a public set accessor

Is there a way to perform such operations (simple rotations/translations) on LineSeries without having to call Clear on it and then Add new transformed DataPoints (which doesn't seem very elegant to me)

like image 508
harveyAJ Avatar asked Sep 06 '25 09:09

harveyAJ


1 Answers

Rather than manipulating points directly in your LineSeries, use MVVM instead: do your calculations in your View Model and then bind results to your View.

enter image description here

ViewModel:

public class MyViewModel
{
    public ObservableCollection<DataPoint> Data1 { get; set; }
    public ObservableCollection<DataPoint> Data2 { get; set; }

    public MyViewModel()
    {
        Data1 = new ObservableCollection<DataPoint>();
        Data2 = new ObservableCollection<DataPoint>();

        double pi = Math.PI;
        double a = pi / 4; // rotation angle
        double fw = 5; // wave frequency
        double fs = 100 * fw; // sampling rate
        double te = 1; // end time
        int size = (int)(fs * te); 

        // do your calculations
        var x1 = Enumerable.Range(0, size).Select(p => p / fs).ToArray();
        var y1 = x1.Select(p => Math.Sin(2*pi*fw*p)).ToArray();

        //populate your Model (original data)
        for (int i = 0; i < y1.Length; i++)
            Data1.Add(new DataPoint(x1[i], y1[i]));

        // transform original data
        var x2 = Data1.Select(p => p.X * Math.Cos(a) - p.Y * Math.Sin(a)).ToArray();
        var y2 = Data1.Select(p => p.X * Math.Sin(a) + p.Y * Math.Cos(a)).ToArray();

        // populate your Model (transformed data)
        for (int i = 0; i < y2.Length; i++)
            Data2.Add(new DataPoint(x2[i], y2[i]));
    }
}

XAML:

<Window x:Class="WpfApp93.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:oxy="http://oxyplot.org/wpf"
        xmlns:local="clr-namespace:WpfApp93"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="350">

    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>

    <Grid>
        <oxy:Plot>
            <oxy:LineSeries ItemsSource="{Binding Data1}"
                            DataFieldX="X"
                            DataFieldY="Y"/>
            <oxy:LineSeries ItemsSource="{Binding Data2}"
                            DataFieldX="X"
                            DataFieldY="Y"/>
        </oxy:Plot>
    </Grid>
</Window>
like image 77
jsanalytics Avatar answered Sep 07 '25 21:09

jsanalytics