pascalabcnet/InteractiveDataDisplay_OneDll/samples/HeatmapSample/MainWindow.xaml.cs

98 lines
3.4 KiB
C#

// Copyright (c) Microsoft Corporation. All Rights Reserved.
// Licensed under the MIT License.
using System;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Reactive.Linq;
namespace HeatmapSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private volatile bool isUnloaded = false;
private AutoResetEvent renderComplete = new AutoResetEvent(false);
private Thread thread;
private double phase = 0;
const int N = 1000;
const int M = 500;
double[] x = new double[N + 1];
double[] y = new double[M + 1];
double[,] f = new double[N, M];
public MainWindow()
{
InitializeComponent();
// Start computation thread when Page appears on the screen
Loaded += (s, e) =>
{
thread = new Thread(ModelRun);
isUnloaded = false;
thread.Start();
};
// Stop computation thread when Page is removed from the screen
Closing += (s, e) =>
{
isUnloaded = true;
renderComplete.Set();
thread.Join();
};
}
private void ModelRun()
{
// Coordinate grid is constant
for (int i = 0; i <= N; i++)
x[i] = -Math.PI + 2 * i * Math.PI / N;
for (int j = 0; j <= M; j++)
y[j] = -Math.PI / 2 + j * Math.PI / M;
while (!isUnloaded) // Run until page is on the screen
{
// Data array is updated
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
f[i, j] = Math.Sqrt(x[i] * x[i] + y[j] * y[j]) * Math.Abs(Math.Cos(x[i] * x[i] + y[j] * y[j] + phase));
phase += 0.1;
// Uncomment next line to simulate delay in computations
// Thread.Sleep(1000);
// Plot the computed array.
// The Plot method must be called from the UI dispatcher thread.
// Unlike Tutoral3 sample here we wait for each frame to be rendered.
if (!isUnloaded)
{
renderComplete.Reset();
PlotDataDel handler = PlotData;
Dispatcher.BeginInvoke(handler);
renderComplete.WaitOne();
}
}
}
private delegate void PlotDataDel();
private void PlotData()
{
// HeatmapGraph objects prepare images to be drawn in a background thread.
// The Plot method cancels current incomplete images before starting a new one.
// This increases responsiveness of the UI but may result in loss of certain
// or even all of the frames.
// The following code shows how to wait until a certain data is actually drawn.
long id = heatmap.Plot(f, x, y); // receive a unique operation identifier
heatmap.RenderCompletion // an observable of completed and cancelled operations
.Where(rc => rc.TaskId == id) // filter out an operation with the known id
.Subscribe(dummy => { renderComplete.Set(); }); // signal when the id is observed
}
}
}