2d visualization笔记(x3) dynamicdatadisplay(sl)(七)

官方
http://research.microsoft.com/en-us/um/cambridge/groups/science/tools/d3/dynamicdatadisplay.htm

Tutorial
http://research.microsoft.com/en-us/um/cambridge/projects/ddd/d3isdk/

D3Overview 必读
http://research.microsoft.com/en-us/um/cambridge/groups/science/tools/d3/D3Overview.pdf

Sliverlight版本: DynamicDataDisplay.2.0.907

Dynamic Data Display 的Sliverlight版本和Wpf版本中的代码不一样.


Dynamic Markers: background computations

方式和笔记(三)一样
xaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

-->
<UserControl x:Class="DynamicMarkerGraphSample.MainPage"
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:d3="clr-namespace:Microsoft.Research.DynamicDataDisplay;assembly=DynamicDataDisplay.Silverlight"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<d3:Chart Name="plotter">
<d3:Chart.Title>
<TextBlock HorizontalAlignment="Center" FontSize="14" Margin="0,5,0,5">Background computations sample</TextBlock>
</d3:Chart.Title>
<d3:CircleMarkerGraph Name="markers" Description="Sine graph" Color="Red" Size="5"/>
</d3:Chart>
</Grid>
</UserControl>

cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Copyright © 2010-2011 Microsoft Corporation, All Rights Reserved.

using System;
using System.Reactive.Linq;
using System.Threading;
using System.Windows.Controls;

namespace
{
public partial class MainPage : UserControl
{
private volatile bool isUnloaded = false;
private AutoResetEvent renderComplete = new AutoResetEvent(false);
private Thread thread;
private double phase = 0;

const int N = 1000;
double[] y = new double[N];

public MainPage()
{
InitializeComponent();
markers.MarkersBatchSize = 1000;

// 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
Unloaded += (s, e) =>
{
isUnloaded = true;
renderComplete.Set();
thread.Join();
};
}

private void ModelRun()
{
while (!isUnloaded)
{
// Data array is updated
for (int i = 0; i < N; i++)
y[i] = Math.Cos(i * Math.PI / 50 + phase);
phase += 0.1;

// Plot the computed array.
// PlotY and Subscribe methods must be called from the UI dispatcher thread.
// Unlike ConcurrentMarkerGraphSample here we wait for each frame to be rendered.
if (!isUnloaded)
{
renderComplete.Reset();
Dispatcher.BeginInvoke(PlotData);
renderComplete.WaitOne();
}
}
}

private void PlotData()
{
// To increase responsiveness of the UI HeatmapGraph objects prepare
// images to be drawn in a background thread. The Plot method cancels
// current incomplete images before starting a new one. This 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 = markers.PlotY(y); // receive a unique operation identifier
markers.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
}
}
}


This sample shows how to plot data that are computed in separated thread. Unlike ConcurrentMarkerGraphSample, in this sample computational thread waits for each frame to be rendered. This is achieved by observing RenderCompletion event and signaling when render operation with specific ID is completed (see ‘PlotData’ method for details).