2006年02月07日

.NETグラフライブラリ「NPlot」



.NET Frameworkが標準で提供するクラスには、グラフを容易に作成するコントロールがありません。Visual Studio .NETではCrystal Reportsでできるようですが(未確認)、その機能や利用条件に満足できない場合や、SharpDevelopなどのVS.NET以外の開発ツールを利用している場合は、別の方法を考えなければいけません。
そこで、.NETアプリケーション開発に無償で利用できる「NPlot」を使ったグラフ作成について、書きたいと思います。

NPlotの入手方法
NPlotはhttp://netcontrols.org/nplot/wiki/から入手できます。

NPlotの利用方法
では、実際にNPlotを利用してグラフを作成してみましょう。
ここでは、SharpDevelop 1.1.0のVB.NETでWindowsアプリケーションを作成するための利用方法を記載します。
C#や、VS.NETなどの他の.NET開発ツールでの利用方法については、適宜読み替えてください。
NPlotでグラフを表示するための最初のステップです。

グラフ表示領域の準備
1. DLLファイルの配置
ダウンロードしたNPlot-?.?.?.?.zipを解凍して「NPlot.dll」をSharpDevelopプロジェクトの実行ファイルが作成されるディレクトリに置きます。
ex.) C:\Document And Settings\USER\SharpDevelop Projects\PROJECT\bin\Debug
gacutilなどで、それ用のエリアにロードする方法もあり

2. 参照を追加
プロジェクトペインの[参照]ノードを右クリックし、[参照]を選択します。
それにより表示される画面の[.NETアセンブリブラウザ]タブを選択し、[参照(B)]をクリックして先ほど配置した「NPlot.dll」を選択します。

3. フォームへのコントロールの配置
ツールペインの「Custom Components」にある「PlotSurface2D」を適当なフォームに配置します。
Custom Componentsには「PlotSurface2D」が2つありますが、「NPlot.Windows.PlotSurface2D」の方です。
ここでは、Nameプロパティを「PlotSurface1」としたものとします。

折れ線グラフ
LinePlotオブジェクトを定義してDataSourceプロパティにデータを入れ、配置したPlotSurface2DにAddします。

Dim LinePlot1 As New Nplot.LinePlot
Dim intData() As Integer = {1,2,3,4,5,6,7,5,3,1}
LinePlot1.DataSource = intData
PlotSurface1.Add(LinePlot1)

棒グラフ
HistogramPlotオブジェクトを定義してDataSourceプロパティにデータを入れ、配置したPlotSurface2DにAddします。
Dim HistogramPlot1 As New Nplot.HistogramPlot
Dim intData() As Integer = {1,2,3,4,5,6,7,5,3,1}
HistogramPlot1.DataSource = intData
PlotSurface1.Add(HistogramPlot1)

ステッププロット
StepPlotオブジェクトを定義してDataSourceプロパティにデータを入れ、配置したPlotSurface2DにAddします。
Dim StepPlot1 As New Nplot.StepPlot
Dim intData() As Integer = {1,2,3,4,5,6,7,5,3,1}
StepPlot1.DataSource = intData
PlotSurface1.Add(StepPlot1)

ポイントプロット
PointPlotオブジェクトを定義してDataSourceプロパティにデータを入れ、配置したPlotSurface2DにAddします。
Dim PointPlot1 As New Nplot.PointPlot
Dim intData() As Integer = {1,2,3,4,5,6,7,5,3,1}
PointPlot1.DataSource = intData
PlotSurface1.Add(PointPlot1)


今回はここまで。
次回以降、画像も交えながら進めたいと思います。

※2006/02/20 間違いや説明不足な点があったので修正しました。申し訳ないです・・・

<<<押して〜
 
posted by kunyami at 13:33 | Comment(18) | TrackBack(0) | .NET - NPlot
この記事へのコメント
初めまして。
いきなりの書き込みスイマセン。

このブログにこういった質問を投げかけて
良いのか分からなく悩みましたが、
どうもNPlotの情報が少なく書かせて
いただきました。
私は現在、簡単なツールを作っているのですが、
NPlotを使ってグラフを書こうと思っている
のですが、どうもうまくいかなくて悩んでます。


それはまずDEMOを実行しようとしても
エラーメッセージが返ってきてしまうこと。
また、全く関係ないC#のプロジェクトの
参照設定にてNPlotを追加したのですが、
ツールボックスにNPlotのアイコンが
表示されないのです。

もし分かりましたらご教授下さい。
また、迷惑でしたらお手数ですが、
このコメントを削除しちゃって下さい。
宜しくお願い致します。

Posted by MIT at 2007年09月17日 21:49
> MITさん
コメントありがとうございます。

DEMOとおっしゃっているのは、配布されている nplot-0.9.10.0.zip内のdemoフォルダにある、csharpのNPlotDemo.slnのプロジェクトを実行するとエラーになるということでしょうか?
もしそうであれば、エラーメッセージを書き込んでいただければわかるかもしれません。

もしもVisual Studio 2005をお使いなのであれば、MSBeeを入れなければいけないのかもしれません。これについては、nplot-0.9.10.0.zip内の、VisualStudio2005_ReadMe.txtをご覧ください。
(私はSharpDevelopを使っているので、Visual Studioのことはわからないのです。すいません...)

Posted by kunyami at 2007年09月17日 23:24
さっそくのご返事ありがとうございます。
エラーは「プロジェクトファイルNPlotDemo.csprojを読み取れません。インポートされたプロジェクト”C:ProgramFile\MSBuild\MSBee\MSBuildExtras.FX1_1.CSharp.targets”が見つかりません。宣言のパスが正しいか、およびファイルがディスクに存在しているかどうかを確認して下さい。」
とのことです。
\MSBuildにMSBeeのファイルを作りMSBuildExtras.FX1_1.CSharp.targetsなどを入れたらここは解決したようなのですが、今度は恐らくフレームワーク1.1でないから無理そうな感じのエラーが出てしまいました。
フレームワーク2.0が入った状態で1.1を入れることができるのでしょうか?

また、新規で作成したプロジェクトの参照設定にてNPlotを追加したのですが、ツールボックスに「PlotSurface2D」が表示されないのですが、普通は表示されるんですよね?


Posted by MIT at 2007年09月19日 19:09
補足ですが、
始めのエラーの件はcsharpのNPlotDemo.slnのプロジェクトを実行したものです。

また、私が使用しているのはVS2005です。

Posted by MIT at 2007年09月19日 19:29
> MITさん

私の環境では、.NET Frameworkの1.1と2.0が同居しています。

SharpDevelopを使っている私は、ツールボックスに「PlotSurface2D」が表示されますが、VisualStudioは使ったことがないのでわかりません…
@ITの掲示板などを見ると、VisualStudio 2005で動かしている人もいらっしゃるようですが…

ちなみに、私がSharpDevelopでコンパイルする限り、.NET Frameworkの1.1、2.0のどちらを対象としても動作しました。

Posted by kunyami at 2007年09月19日 20:54
ありがとうございます。
.NET Frameworkは解決したようですが、
今度はNPlotDemo.slnを実行すると次のようなエラーメッセージが出てしまいます。
項目 "obj\FX1_1\Release\NPlotDemo.AxisTestsForm.resources" は "Resources" パラメータで 1 度以上指定されました。重複した項目は "Resources" パラメータではサポートされていません。
ご存じであればぜひ教えて下さい。
宜しくお願いします。

Posted by MIT at 2007年09月20日 04:17
> MITさん

なぜエラーになるのでしょうね?
私の環境ではエラーが出ないのですが…
エラーメッセージに提示されているファイルとその行を見てみればわかりませんかね?

Posted by kunyami at 2007年09月20日 09:02
エラーメッセージ「項目 "obj\FX1_1\Release\NPlotDemo.AxisTestsForm.resources" は "Resources" パラメータで 1 度以上指定されました。重複した項目は "Resources" パラメータではサポートされていません。」
は解決出来ました。
ソリューションエクスプローラーにてNPlotDemo.csproj\AxisTestsForm.cs\AxisTestsForm.resxが存在していた為です。
なのでAxisTestsForm.resxファイルを削除してやれば解決出来ます。

実行しグラフは出るようになったのですが、
未だツールボックスには「PlotSurface2D」が表示されてきません。

また分かったら書き込みしたいと思います。

色々調べて頂きありがとうございました。

Posted by MIT at 2007年09月20日 19:51
こちらのページでNPlotを知りました。
まとまっていて、非常に参考になりました。
ありがとうございます。

私は、サンプリングしたデータを動的に
散布図にしたいのですが、横軸が移動して
いくので、範囲外(左側)は消去して残り
は画面移動(左へ)新しいデータは追加分
だけ描画なんてことは出来ないでしょうか?

毎回描画すると処理時間分サンプリングと
ずれるもので、良い方法がないか模索中です。

自分でも分かったら、こちらへ書き込みたい
と思います。

Posted by tgw at 2008年11月03日 19:04
> tgwさん
コメントありがとうございます。

毎回全体を描画することになるのは仕方ないですね。

私はそのようなことがしたい場合には、グラフデータ(値)の保持のためにArrayListやDataTableを使って、配列の先頭を削除(ex. ArrayList.RemoveAt(0))して最後に追加(ex. ArrayList.Add(value))するといったことを行っています。

これでWindowsFormであればPlotSurface2D.Refresh()すれば移動したようになるはずです。

複数のplotを配置して1秒間隔とかで移動させようとすると、かなり負荷が高くなってしまいますが今のところは諦めています・・・

もっと良い方法あると良いんですけどね。

Posted by kunyami at 2008年11月03日 21:07
tgwです。
レスポンス頂きありがとうございます。

私も、今DataTableを使ってNPlotに
割り当て様と奮闘中!です。

サンプリングデータはDataTableに
書き込み、フィールドをNPlotに
割り当てようとしております。

また、進展しましたらこちらへ
書き込ませていただきます。

Posted by tgw at 2008年11月11日 21:54
> tgwさん
DataTableはちょっとメンドクサイですよね。
良い結果を楽しみにしてます。
がんばってってください!

Posted by kunyami at 2008年11月11日 22:46
やっと目的に近い事が実現しました。
これもこちらで勉強させて頂いたおかげです。
ありがとうございます。m(..)m

苦労した事はDataTableでは
1.
NPlotのDataSourceにそのまま列を割り当てられず
DataTableから列毎に一々配列にしてあげなければ
いけないのでパフォーマンスに難があり、
結果やめました。

2.
ArrayListにして流れるグラフが出来るようになり
よしっ!と思っていたら、CPUが次第に100%に
なってしまい、表示データの量をいくら変えても
収まらなく苦労しました。
どうやら、Refreshだけでは、一度書き込んだ
データはPlotSurface2Dが持ったままの様でして
ArrayListに無い筈のデータ(既にRemoveした)
が描画されていました。

結果、Refreshの前にClearをいれると解決できま
した。

時間掛かりましたが、大変良い勉強になりました。

後は、マウスを当てた時の座標ラベルの書式
が日付になればと思うのですが・・・
がんばってみます。


Posted by tgw at 2008年11月23日 00:12
tgwです。
座標ラベルの書式->ツールチップでした。
ちなみに、X軸がDateTimeの場合、そのままでは
シリアル値が出てしまい、意味不明です。

ツールチップを日付時間書式で表示させる場合は
PlotSurface2D1.DateTimeToolTip() = True
とすれば、大丈夫でした。

参考に、
PlotSurface2D1.AddInteraction(New NPlot.Windows.PlotSurface2D.Interactions.HorizontalDrag()) 
横方向にマウスでドラッグ可。
同様に
.VerticalDrag() で縦方向のドラッグの設定が
出来ました。

NPlotって使えますね〜。
こちらで随分勉強させてもらったおかげです。
ありがとうございました。
   

Posted by tgw at 2008年11月24日 13:43
tgwです。いつも勉強させていただいております。

どうしても、行き詰ってしまい、こちらへ投稿
すべきか迷いましたが、失礼ながら、ご質問させてください。

バージョン:NPlot is 0.9.10.0.
このNPlotDemoの中に色々なDemoサンプルがあります。

"Multi Plot Demo"ボタンを押すと、FinancialDemo.CS
が表示します。

これと同じ動作をしたいのですが、
サンプルはC#で記述されており、VB2008で書き直しても
エラーが出て動作させることが出来ません。

具体的には、

エラー 5
'Public Event InteractionOccured(sender As Object)'
はイベントであるため、直接呼び出すことはできません。
イベントを発生させるには
'RaiseEvent' ステートメントを使用してください。

と、出ます。

C#では、InteractionOccuredはあるのですが、
VB2008では出てきません。
調べたところ、C#とVBではアクセサ?の使い方が
違うようなのですが、具体的な記述方法が分かりません。

こちらのページではC#とVBの記述があり分かり易かった為、
投稿致しました。

よろしくお願いいたします。

Posted by tgw at 2008年12月22日 00:08
> tgwさん
こんにちは、返事が遅くなってしまってすいません。

どのように書き換えていらっしゃるのかわからないので何とも言い難いですが
AddHandlerしてますか?
----------------------------------
AddHandler costPS.InteractionOccured, AddressOf costPS_InteractionOccured
....
Private Sub costPS_InteractionOccured(ByVal sender As Object)
  Dim axis As New DateTimeAxis(costPS.XAxis1)
  axis.Label = "Date / Time"
  axis.HideTickText = False
  Me.volumePS.XAxis1 = axis
  Me.volumePS.Refresh()
End Sub
----------------------------------
とかするといいのかな?

Posted by kunyami at 2008年12月25日 12:40
こちらこそご返事頂きながら、ご連絡が遅くなり、大変失礼いたしました。

AddHandlerですか、このような使用方法があったのですね、参考になりました。

さっそく試してみます。

Posted by tgw at 2009年01月10日 23:49
はじめまして。C#を始めて日が浅いものです。
計測データをグラフ表示する必要があり、Nplotが使えるようなので検索していて、
こちらに来ました。大変参考になります。ありがとうございます。
私はVisual Studio 2008を使っていますが、0.9.10.0のデモを実行する際、
MITさん同様のエラーが起こりました。これは、MSBee(その前に、.NET Framework1.1、同日本語パック、同SP1、同SDKをインスト)をインストし、デモを一度開いて.NET Framework2.0で保存しなおしたら、解決できました。
でも、やはりプロジェクトの参照設定でNPlotを追加してもツールボックスに「PlotSurface2D」というのは表示されません...

Posted by snowyowl at 2009年02月04日 22:19
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/12916797
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック