2016-03-31 250 views
4

ヒートマップをプロットするグラフがあります。私が持っている唯一のデータは湿度と温度です。これはグラフの中の一点を表しています。2Dヒートマップをプロットする

グラフの長方形のヒートマップをC#で取得するにはどうすればよいですか?

私が欲しいのは下図のようになります。私が本当にしたいことは、私はリストから取得する点に基づいて異なる色でプロットされたグラフの矩形領域である

enter image description here

チャート内のカラフルなセクションをポイントして形成します。

+1

問題は、あなたの問題がわからないということです。コードはありますか?なぜそれは働いていないのですか? [faq]と[ask]をお読みください。 – Marco

答えて

7

ヒートマップを構成する色の付いた四角形でチャートを作成するには、少なくとも3つの方法があります。

ここには、example があり、/ abusesにはDataGridViewが使用されています。私はこれを示唆しませんが、投稿にはあなたの仕事で使う素晴らしいカラーリストを作成する便利な機能が含まれています。

次に、GDI +メソッド、つまりGraphics.FillRectangleを使用してグラフを描画するオプションがあります。これは難しいことではありませんが、スケーリング、軸、ツールチップなど、Chartコントロールが提供する素敵なエキストラを手に入れたいと思ったら、作業が追加されます。以下を参照してください!

したがって、オプション3を見てみましょう。DataVisualization名前空間のChartコントロールを使用します。

List<Color> colorList = new List<Color>(); 

そして、あなたは色のリストに指し示すint型のインデックスの2次元アレイ上にデータを投影する管理していること:

int[,] coloredData = null; 

てみましょう最初のあなたは色のリストを作成していることを前提としてい

S1.ChartType = SeriesChartType.Point; 
0:

次はあなたのためにChartTypeを選択する必要がSeries S1本当に唯一のに役立ちます私はそれを考えることができるものがあります

ポイントはMarkersで表示されます。私たちはDataPointsを実際には標準MarkerTypesの1つとして表示しません。

Square私たちが四角形を表示したければOKです。長方形の場合はうまくいきません:重なり合わせても、完全に重なっていないため、異なるサイズの境界にポイントが残っています。

したがって、カスタムマーカーを使用します。各点のMarkerImageを適切なサイズと色のビットマップに設定します。ここで

は、私たちのSeriesDataPointsを追加し、MarkerImageを持つように各セットのループです:

for (int x = 1; x < coloredData.GetLength(0); x++) 
    for (int y = 1; y < coloredData.GetLength(1); y++) 
    { 
     int pt = S1.Points.AddXY(x, y); 
     S1.Points[pt].MarkerImage = "NI" + coloredData[x,y]; 

    } 

これは、いくつかの説明を行いますディスク上のパスにないMarkerImageを設定するには、 Chart's Imagesコレクションに存在する必要があります。この手段は、タイプがNamedImageである必要があります。どんなイメージでも行いますが、それを識別するために一意の名前文字列を追加する必要があります(NamedImagesCollection)。私は「NI1」、「NI2」という名前を選んだ。

明らかにこれらのイメージをすべて作成する必要がある。ここにそれを行う機能があります:

void createMarkers(Chart chart, int count) 
{ 
    // rough calculation: 
    int sw = chart.ClientSize.Width/coloredData.GetLength(0); 
    int sh = chart.ClientSize.Height/coloredData.GetLength(1); 

    // clean up previous images: 
    foreach(NamedImage ni in chart1.Images) ni.Dispose(); 
    chart.Images.Clear(); 

    // now create count images: 
    for (int i = 0; i < count; i++) 
    { 
     Bitmap bmp = new Bitmap(sw, sh); 
     using (Graphics G = Graphics.FromImage(bmp)) 
      G.Clear(colorList[i]); 
     chart.Images.Add(new NamedImage("NI" + i, bmp)); 
    } 
} 

すべてのマーカーが少なくともおおよそ正しいサイズを持つようにします。そうwhenevet我々は再びそれを設定し、そのサイズの変更:

void setMarkerSize(Chart chart) 
{ 
    int sx = chart1.ClientSize.Width/coloredData.GetLength(0); 
    int sy = chart1.ClientSize.Height/coloredData.GetLength(1); 
    chart1.Series["S1"].MarkerSize = (int)Math.Max(sx, sy); 
} 

これはに描画する、すなわち、実際の面積をInnerPlotPositionなどの詳細についてはあまり気にしません。だからここに洗練のためのいくつかの部屋です!

我々はチャートを設定するときに我々はをリサイズ時だけでなく、これを呼び出す:

private void chart1_Resize(object sender, EventArgs e) 
{ 
    setMarkerSize(chart1); 
    createMarkers(chart1, 100); 
} 

のは、いくつかの安価なテストデータを使用して結果を見てみましょう:

enter image description hereenter image description here

として、あなたはサイズ変更が正常に動作するのを見ることができます。

私の例を設定します。

private void button6_Click(object sender, EventArgs e) 
{ 
    List<Color> stopColors = new List<Color>() 
    { Color.Blue, Color.Cyan, Color.YellowGreen, Color.Orange, Color.Red }; 
    colorList = interpolateColors(stopColors, 100); 

    coloredData = getCData(32, 24); 
    // basic setup.. 
    chart1.ChartAreas.Clear(); 
    ChartArea CA = chart1.ChartAreas.Add("CA"); 
    chart1.Series.Clear(); 
    Series S1 = chart1.Series.Add("S1"); 
    chart1.Legends.Clear(); 
    // we choose a charttype that lets us add points freely: 
    S1.ChartType = SeriesChartType.Point; 

    Size sz = chart1.ClientSize; 

    // we need to make the markers large enough to fill the area completely: 
    setMarkerSize(chart1); 
    createMarkers(chart1, 100); 

    // now we fill in the datapoints 
    for (int x = 1; x < coloredData.GetLength(0); x++) 
     for (int y = 1; y < coloredData.GetLength(1); y++) 
     { 
      int pt = S1.Points.AddXY(x, y); 
      // S1.Points[pt].Color = coloredData[x, y]; 

      S1.Points[pt].MarkerImage = "NI" + coloredData[x,y]; 
     } 
} 

いくつかの注意事項を制限に:

  • ポイントは常にすべてのグリッド線の上に上に座ります。あなたが本当にそれらを必要とする場合は、Paintイベントの1つの上にそれらを描画する必要があります。

  • 示されているラベルは、データ配列の整数インデックスを参照しています。元のデータを表示する場合は、軸にを追加する方法もあります。here for an exampleを参照してください。

これは、Chartコントロールを使用してできることを示します。ここにあなたの混乱を完了するには、同じ色とデータを使用してGDI +でこれらの四角形を描画する方法である:

Bitmap getChartImg(float[,] data, Size sz, Padding pad) 
{ 
    Bitmap bmp = new Bitmap(sz.Width , sz.Height); 
    using (Graphics G = Graphics.FromImage(bmp)) 
    { 
     float w = 1f * (sz.Width - pad.Left - pad.Right)/coloredData.GetLength(0); 
     float h = 1f * (sz.Height - pad.Top - pad.Bottom)/coloredData.GetLength(1); 
     for (int x = 0; x < coloredData.GetLength(0); x++) 
      for (int y = 0; y < coloredData.GetLength(1); y++) 
      { 
       using (SolidBrush brush = new SolidBrush(colorList[coloredData[x,y]])) 
        G.FillRectangle(brush, pad.Left + x * w, y * h - pad.Bottom, w, h); 
      } 

    } 
    return bmp; 
} 

結果のビットマップはおなじみになります

簡単だった

enter image description here

。パディングによって予約されているスペースにすべてのエキストラを追加するのは簡単ではありません。

+0

答えをありがとう、私はそれからいくつかの論理をつかむ。 – LittleThunder

関連する問題