ヒートマップをプロットするグラフがあります。私が持っている唯一のデータは湿度と温度です。これはグラフの中の一点を表しています。2Dヒートマップをプロットする
グラフの長方形のヒートマップをC#で取得するにはどうすればよいですか?
私が欲しいのは下図のようになります。私が本当にしたいことは、私はリストから取得する点に基づいて異なる色でプロットされたグラフの矩形領域である
チャート内のカラフルなセクションをポイントして形成します。
ヒートマップをプロットするグラフがあります。私が持っている唯一のデータは湿度と温度です。これはグラフの中の一点を表しています。2Dヒートマップをプロットする
グラフの長方形のヒートマップをC#で取得するにはどうすればよいですか?
私が欲しいのは下図のようになります。私が本当にしたいことは、私はリストから取得する点に基づいて異なる色でプロットされたグラフの矩形領域である
チャート内のカラフルなセクションをポイントして形成します。
ヒートマップを構成する色の付いた四角形でチャートを作成するには、少なくとも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
を適切なサイズと色のビットマップに設定します。ここで
は、私たちのSeries
にDataPoints
を追加し、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);
}
のは、いくつかの安価なテストデータを使用して結果を見てみましょう:
として、あなたはサイズ変更が正常に動作するのを見ることができます。
私の例を設定します。
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;
}
結果のビットマップはおなじみになります
簡単だった。パディングによって予約されているスペースにすべてのエキストラを追加するのは簡単ではありません。
答えをありがとう、私はそれからいくつかの論理をつかむ。 – LittleThunder
問題は、あなたの問題がわからないということです。コードはありますか?なぜそれは働いていないのですか? [faq]と[ask]をお読みください。 – Marco