我有一张图表,我想绘制一张热图;我拥有的唯一数据是湿度和温度,它们代表了图表中的一个点。绘制二维热图
如何在c#中的图表上获取矩形类型的热图?
我想要的是类似下面的图片:
我真正想要的是图表中的矩形区域,该区域被不同颜色的基础上,我从列表中得到点绘制点和形成图表中的彩色部分。
我有一张图表,我想绘制一张热图;我拥有的唯一数据是湿度和温度,它们代表了图表中的一个点。绘制二维热图
如何在c#中的图表上获取矩形类型的热图?
我想要的是类似下面的图片:
我真正想要的是图表中的矩形区域,该区域被不同颜色的基础上,我从列表中得到点绘制点和形成图表中的彩色部分。
您可以选择至少三种方式来创建包含组成热图的彩色矩形的图表。
这里是一个example 使用/滥用DataGridView
。虽然我不会提出这个建议,但是这篇文章包含了一个有用的函数,可以创建漂亮的颜色列表以用于任务。
然后可以选择使用GDI +方法绘制图表,即Graphics.FillRectangle
。这并不难,但一旦你想得到一个Chart控件提供的那些很好的附加功能,比如缩放,坐标轴,工具提示等,这些工作就会加起来。
所以让我们来看看选项三:使用DataVisualization
命名空间中的Chart
控件。
让我们先假设你已经创建了一个颜色列表:
List<Color> colorList = new List<Color>();
而且你已成功地投射你的数据在INT索引的二维数组到这点颜色列表:
int[,] coloredData = null;
接下来,您必须选择适合您的一个ChartType
Series S1
真的是我唯一能想到的,这将有助于:
S1.ChartType = SeriesChartType.Point;
积分用Markers
显示。我们希望DataPoints
不是真正显示为标准MarkerTypes之一。
Square
会好的,如果我们想显示正方形;但对于矩形它不会很好地工作:即使我们让它们重叠,仍然会有不同大小的边界点,因为它们不会完全重叠。
因此我们使用定制 marker将每个点的MarkerImage
设置为合适大小和颜色的位图。
这是一个循环,增加了DataPoints
我们Series
,并设置每个有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);
}
让我们用一些廉价的TESTDATA看看结果:
由于你可以看到调整大小工程确定..
这是完整的代码建立我的例子:
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
事件中的其中一个上绘制它们。
所示的标签是指数据数组的整数索引。如果要显示原始数据,一种方法是将CustomLabels
添加到轴上。请参阅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
问题是,您不知道自己的问题是什么。你有代码吗?为什么它不工作?请阅读[常见问题]和[问]。 – Marco