Windows 7 Sensor & Location Platformを使ってみよう – その6


あーっと言う間に年末ですね。気温も随分下がって、寒い毎日が続いていますねっ。私はノースブルー生まれ(嘘です。単なる北国生まれです)のわりに、寒さに弱いので往生してますが、気温と言えば、小学校の夏休みの宿題で、課題研究というのがあって、ある年、何もネタが思い付かず、夏休み中の温度を2学期の始業式直前に新聞をひっくり返しつつ、片っぱしから書き出して、グラフと、お天気マークを入れていったことが思い出されます。あんときゃぁ、しんどかったぜぃ…って、もうかなり昔のことなので良くは覚えていないんですけどぅ。


前置きが長くなりましたが、Windows 7のSensor APIで温度を計測したとき、それをグラフにしたくなりますね。というわけで、今回は取得したデータを表示する方法として、WPFのChartコントロールを紹介します。


このコントロール、Visual Studio 2008 SP1(.NET Framework V3.5 SP1)までは、WPF Toolkitとして公開されていました。Visual Studio 2010(.NET Framework V4.0)からは、標準の部品として加わったようです。WPFのツールボックスに“Data Visualization”というカテゴリーがあって、そこに、Chartという名前でリストに入っています。XAMLのデザイナーで、ツールボックスからドラッグ&ドロップすればすぐ使えます。


Chart Control


このChartコントロール、棒グラフや折れ線グラフ、円グラフ、等々、かなりいろんなグラフの種類がサポートされていて、で、もちろん、Data Bindingも出来るし、凡例やラベルをStyleで指定できるので、見栄えの良いグラフを簡単に、そして、動的に描画することができる、優れモノです。多分、一般的に、データを収集、テキストファイルとして保存、Excelに読み込み、グラフ作成、・・・みたいな流れをやっちゃう人がたくさんいる?、もしくはOpenGL等を使ってゴリゴリ書くのが、理系の技術者の発想のような気がしますが、そんな手間は一切要りません。Silverlihgtでももちろん使えます。この忙しい年の瀬、やりたいことがパッとできるって、ありがたいよね。


上の図は、ツールボックスからドラッグ&ドロップして、そのあと、以下のように成形した状態。(Visual Studio 2010を利用)






<Window x:Class=”…”
        xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation
        xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml
        Title=”Graph” Height=”400″ Width=”600″
      
 xmlns:chartingToolkit=
            “clr-namespace:System.Windows.Controls.DataVisualization.Charting;
            assembly=System.Windows.Controls.DataVisualization.Toolkit”>
    <Window.Resources>
        <Style x:Key=”DateTimeAxisLabelStyle1″
            TargetType=”{x:Type chartingToolkit:DateTimeAxisLabel}”>
            <Setter Property=”StringFormat”
                 Value=”{}{0:yyyy/MM/dd HH:mm:ss}”/>
            <Setter Property=”RenderTransform”>
               ※ ここ何やってるかというとグラフの目盛の値が
               ※ 表示の際重ならないように、位置ずらし、斜め化してる
                <Setter.Value>                  
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform Angle=”315″/>
                        <TranslateTransform Y=”70″/>
                    </TransformGroup>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <DockPanel>
        <chartingToolkit:Chart Name=”chart” Title=”Trend of Sensor Values” >
            <chartingToolkit:Chart.Axes>
                <chartingToolkit:LinearAxis Orientation=”Y”/>
                <chartingToolkit:DateTimeAxis Orientation=”X”/>
            </chartingToolkit:Chart.Axes>
            <chartingToolkit:LineSeries
                x:Name=”chartLineSeries1″
                ItemsSource=”{Binding}”
                DependentValuePath=”Value”
                IndependentValuePath=”Key”/>
            <chartingToolkit:LineSeries …
             …. 以下、Nameを変えて、計6個繰り返し…
         </chartingToolkit:Chart>
    </DockPanel>
</Window>


この例では、折れ線グラフなので、<Chart>~</Chart>の子要素として、<LineSeries/>を使っているけど、棒グラフや円グラフの場合は、対応するクラスがあるので、そちらを使えばよい。最初の方の<Style/>で、軸の表示方法を指定しているんだ。そして、<LineSeries/>の属性で、DependentValuePath属性と、IndependentValuePath、ItemSourceを指定しているけど、最初のが、Y軸方向(縦軸)の値を格納するプロパティの名前、次がX軸方向(横軸)の値を格納するプロパティの名前を指定している。ItemSourceは{Binding}とだけ記載しているけど、これで十分。ここにはコードビハインドで、System.Collections.Generic.KeyValuePair<T,K>のListを指定するんだ。KeyValuePairは、KeyとValueという二つのプロパティを持っているので、それが、XAMLの指定を通じて、IndependentValuePath、DependentValuePathに対応づけられるという訳だ!!。
Windows 7 Sensor & Location Platformのセンサーは、センサー値の計測時間と、センサー値群をAPIを通じて供給してくるので、たとえば、KeyValuePair<DateTime,double>といったような使い方をすれば良い。


で、コードビハインドのほうは、まず、List<KeyValuePair<DateTime,Double>>  myLineSeriesSource というプライベートメンバー変数を用意しておき、センサーから値を取得したら、myLineSeriesSourceにKeyValuePairを一個追加して、lineSerieseのDataContextプロパティを更新すればよい。そうすれば、後はWPFが自動的にグラフを再描画してくれるんだ。






private List<KeyValuePair<DateTime,Double>> myLineSeriesSource = new …;

public void AddDataToLineSeriese(DateTime measuredTime, Double value)
{
    myLineSeriesSource.Add(new KeyValuePair<DateTime, Double>(measuredTime, value);
    chartLineSeries1.DataContext = myLineSeriesSource.ToArray();
}

public delegate void AddDataToLineSeriesDelegator(DateTime x, double y);
public void AddDataToLineSeriesAsync(DateTime x, double y)
{
    this.Dispatcher.BeginInvoke(
        new AddDataToLineSeriesDelegator(AddDataToLineSeries),
        new object[] { x, y });
}


そうそう、センサー値をハンドラーで取得(非同期で受信)する場合は、スレッドが違うから、上のコードのようにBeginInvokeを通じて登録するコードも書いておくとよいね。他には、LineSeriesやその他関連クラスのプロパティが豊富にあるんで、そのあたりを色々と設定すると見栄えばっちりだよ。


見栄えを整えて、センサーの複数の値に対応するようにちょっと変えて、さらに、実際の3軸加速度センサーの値でグラフを描画すると、下のようになるんだよ。



※Z軸下向き→X軸上向き→Z軸上向き→Y軸上向き→X軸上向き→X軸下向きにしてみた


Chartの詳しい説明は、
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datavisualization.charting.chart(VS.100).aspx
を見てね。万一(ってデフォルトはこっちか?)、ツールボックスにChartコントロールがない場合は、ツールボックスビューで右クリック→”Choose Items”(アイテムを選択)で、表示されるダイアログのリストで探して、チェックをつけると表示されるよ。


ふぅ、こんなに頻繁にブログに投稿するのは初めてで、ちょっと息切れしてるけど、使ってみようシリーズは、一応これでおしまいということで。次からは、「Windows 7 Sensor & Locationのドライバーを書いてみよう」を始めるよっ。じゃぁ、また。


 目次へ

Comments (0)

Skip to main content