1.前言
用C#所繪製的圖表中加入色彩條圖例顯示,用以區分數值大小。
2.說明
ColorMap的類別可參考codeproject的"Create Custom Color Maps in C#"說明
http://www.codeproject.com/Articles/18150/Create-Custom-Color-Maps-in-C

測試資料是由R導出的資料集,輸出檔案格式為CSV

df <- data.frame(x=rnorm(10000),y=rnorm(10000))
write.table(df,file='d:/temp/sim.csv',row.names=FALSE,sep=',')

ColorMap類別

public class ColorMap
{
	private int colormapLength = 255;
	private int alphaValue = 255;

	public ColorMap()
	{
	}

	public ColorMap(int colorLength)
	{
		colormapLength = colorLength;
	}

	public ColorMap(int colorLength, int alpha)
	{
		colormapLength = colorLength;
		alphaValue = alpha;
	}

	public int[,] Spring()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[] spring = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			spring[i] = 1.0f * i / (colormapLength - 1);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = 255;
			cmap[i, 2] = (int)(255 * spring[i]);
			cmap[i, 3] = 255 - cmap[i, 1];
		}
		return cmap;
	}

	public int[,] Summer()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[] summer = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			summer[i] = 1.0f * i / (colormapLength - 1);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = (int)(255 * summer[i]);
			cmap[i, 2] = (int)(255 * 0.5f * (1 + summer[i]));
			cmap[i, 3] = (int)(255 * 0.4f);
		}
		return cmap;
	}

	public int[,] Autumn()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[] autumn = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			autumn[i] = 1.0f * i / (colormapLength - 1);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = 255;
			cmap[i, 2] = (int)(255 * autumn[i]);
			cmap[i, 3] = 0;
		}
		return cmap;
	}

	public int[,] Winter()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[] winter = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			winter[i] = 1.0f * i / (colormapLength - 1);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = 0;
			cmap[i, 2] = (int)(255 * winter[i]);
			cmap[i, 3] = (int)(255 * (1.0f - 0.5f * winter[i]));
		}
		return cmap;
	}

	public int[,] Gray()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[] gray = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			gray[i] = 1.0f * i / (colormapLength - 1);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = (int)(255 * gray[i]);
			cmap[i, 2] = (int)(255 * gray[i]);
			cmap[i, 3] = (int)(255 * gray[i]);
		}
		return cmap;
	}

	public int[,] Jet()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[,] cMatrix = new float[colormapLength, 3];
		int n = (int)Math.Ceiling(colormapLength / 4.0f);
		int nMod = 0;
		float[] fArray = new float[3 * n - 1];
		int[] red = new int[fArray.Length];
		int[] green = new int[fArray.Length];
		int[] blue = new int[fArray.Length];

		if (colormapLength % 4 == 1)
		{
			nMod = 1;
		}

		for (int i = 0; i < fArray.Length; i++)
		{
			if (i < n)
				fArray[i] = (float)(i + 1) / n;
			else if (i >= n && i < 2 * n - 1)
				fArray[i] = 1.0f;
			else if (i >= 2 * n - 1)
				fArray[i] = (float)(3 * n - 1 - i) / n;
			green[i] = (int)Math.Ceiling(n / 2.0f) - nMod + i;
			red[i] = green[i] + n;
			blue[i] = green[i] - n;
		}

		int nb = 0;
		for (int i = 0; i < blue.Length; i++)
		{
			if (blue[i] > 0)
				nb++;
		}

		for (int i = 0; i < colormapLength; i++)
		{
			for (int j = 0; j < red.Length; j++)
			{
				if (i == red[j] && red[j] < colormapLength)
				{
					cMatrix[i, 0] = fArray[i - red[0]];
				}
			}
			for (int j = 0; j < green.Length; j++)
			{
				if (i == green[j] && green[j] < colormapLength)
					cMatrix[i, 1] = fArray[i - (int)green[0]];
			}
			for (int j = 0; j < blue.Length; j++)
			{
				if (i == blue[j] && blue[j] >= 0)
					cMatrix[i, 2] = fArray[fArray.Length - 1 - nb + i];
			}
		}

		for (int i = 0; i < colormapLength; i++)
		{
			cmap[i, 0] = alphaValue;
			for (int j = 0; j < 3; j++)
			{
				cmap[i, j + 1] = (int)(cMatrix[i, j] * 255);
			}
		}
		return cmap;
	}

	public int[,] Hot()
	{
		int[,] cmap = new int[colormapLength, 4];
		int n = 3 * colormapLength / 8;
		float[] red = new float[colormapLength];
		float[] green = new float[colormapLength];
		float[] blue = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			if (i < n)
				red[i] = 1.0f * (i + 1) / n;
			else
				red[i] = 1.0f;
			if (i < n)
				green[i] = 0f;
			else if (i >= n && i < 2 * n)
				green[i] = 1.0f * (i + 1 - n) / n;
			else
				green[i] = 1f;
			if (i < 2 * n)
				blue[i] = 0f;
			else
				blue[i] = 1.0f * (i + 1 - 2 * n) / (colormapLength - 2 * n);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = (int)(255 * red[i]);
			cmap[i, 2] = (int)(255 * green[i]);
			cmap[i, 3] = (int)(255 * blue[i]);
		}
		return cmap;
	}

	public int[,] Cool()
	{
		int[,] cmap = new int[colormapLength, 4];
		float[] cool = new float[colormapLength];
		for (int i = 0; i < colormapLength; i++)
		{
			cool[i] = 1.0f * i / (colormapLength - 1);
			cmap[i, 0] = alphaValue;
			cmap[i, 1] = (int)(255 * cool[i]);
			cmap[i, 2] = (int)(255 * (1 - cool[i]));
			cmap[i, 3] = 255;
		}
		return cmap;
	}
}

資料轉成DataTable

public DataTable TxtConvertToDataTable(string File, string TableName, string delimiter)
{
	DataTable dt = new DataTable();
	DataSet ds = new DataSet();
	StreamReader s = new StreamReader(File, System.Text.Encoding.Default);
	//string ss = s.ReadLine();//skip the first line
	string[] columns = s.ReadLine().Split(delimiter.ToCharArray());
	ds.Tables.Add(TableName);
	foreach (string col in columns)
	{
		bool added = false;
		string next = "";
		int i = 0;
		while (!added)
		{
			string columnname = col + next;
			columnname = columnname.Replace("#", "");
			columnname = columnname.Replace("'", "");
			columnname = columnname.Replace("&", "");

			if (!ds.Tables[TableName].Columns.Contains(columnname))
			{
				ds.Tables[TableName].Columns.Add(columnname.ToUpper());
				added = true;
			}
			else
			{
				i++;
				next = "_" + i.ToString();
			}
		}
	}

	string AllData = s.ReadToEnd();
	string[] rows = AllData.Split("\n".ToCharArray());

	foreach (string r in rows)
	{
		string[] items = r.Split(delimiter.ToCharArray());
		ds.Tables[TableName].Rows.Add(items);
	}

	s.Close();

	dt = ds.Tables[0];

	return dt;
}

繪圖

private void DrawChart(DataTable dt, ColorMap map, Graphics g, float min, float max)
{
	int[,] cmap = new int[254, 4];
	cmap = map.Jet();
	int m = 254;
	for (int i = 0; i < dt.Rows.Count; i++)
	{
		float posx = float.Parse(dt.Rows[i]["x"].ToString());
		float posy = float.Parse(dt.Rows[i]["y"].ToString());
		float val = float.Parse(dt.Rows[i]["y"].ToString());
		int colorIndex = (int)((val - min) * m / (max - min));
		SolidBrush s = new SolidBrush(Color.FromArgb(cmap[colorIndex, 0], cmap[colorIndex, 1], cmap[colorIndex, 2], cmap[colorIndex, 3]));
		RectangleF rec = new RectangleF(posx, posy, 5, 5);
		g.FillEllipse(s, rec);
		g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
		g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
		
		s.Dispose();
	}
}

加入色彩條圖例顯示

private void DrawColorBar(Graphics g, int x, int y, int width, int height, float min, float max, ColorMap map)
{
	int[,] cmap = new int[254, 4];
	cmap = map.Jet();            

	int bmin = 0;
	int bmax = height;
	int dy = (bmax - bmin) / height;
	int m = 254;
	for (int i = 0; i < bmax; i++)
	{
		int colorIndex = (int)((i - bmin) * m / (bmax - bmin));
		SolidBrush aBrush = new SolidBrush(Color.FromArgb(cmap[colorIndex, 0], cmap[colorIndex, 1], cmap[colorIndex, 2], cmap[colorIndex, 3]));
		g.FillRectangle(aBrush, x, y + i * dy, width, dy);
	}

	//在Color bar上加入刻度線與標籤
	float ticklength = 0.3f * width;
	Pen p = new Pen(Color.Black, 1);
	StringFormat sFormat = new StringFormat();
	sFormat.Alignment = StringAlignment.Near;
	SizeF size = g.MeasureString("T", new Font("Arial", 7, FontStyle.Regular, GraphicsUnit.Pixel));
	g.DrawLine(p, x + width, y + height, x + width, y);
	for (float i = min; i <= max; i += (max - min) / 6)
	{
		g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
		g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

		float yy = y + height - (i - min) * height / (max - min);
		g.DrawLine(p, x + width + 5, yy, x + width - ticklength + 5, yy);
		g.DrawString((Math.Round(i, 2)).ToString(), new Font("Arial", 7), Brushes.Black, new PointF(x + width + 5, yy - size.Height / 2), sFormat);
		
	}
}

3.應用

private void btPlot_Click(object sender, EventArgs e)
{
	//讀取數值資料
	DataTable dt = TxtConvertToDataTable(@"D:\Temp\sim.csv", "tmp", ",");
	for (int i = 0; i < dt.Rows.Count; i++)
	{
		dt.Rows[i]["x"] = (double.Parse(dt.Rows[i]["x"].ToString()) * 50 + 250).ToString();
		dt.Rows[i]["y"] = (double.Parse(dt.Rows[i]["y"].ToString()) * 50 + 250).ToString();
	}

	//計算繪圖區數值的最大值與最小值
	float max = float.MinValue;
	float min = float.MaxValue;
	for (int i = 0; i < dt.Rows.Count; i++)
	{
		if (dt.Rows[i]["y"].ToString() != "")
		{
			float _value = float.Parse(dt.Rows[i]["y"].ToString());
			if (max < _value) max = _value;
			if (min > _value) min = _value;
		}
	}

	//新增Bitmap影像
	Image img = new Bitmap(500, 500);
	//在image上繪圖
	Graphics g = Graphics.FromImage(img);
	//建立ColorMap類別實例化
	ColorMap map = new ColorMap();
	//繪圖
	DrawChart(dt, map, g, min, max);
	//繪製色彩條圖例
	DrawColorBar(g, 450, 50, 15, 400, min, max, map);
	//顯示影像檔
	pictureBox1.Image = img;       
}

圖例

sim_colorbar_20130924  

arrow
arrow
    文章標籤
    C# ColorBar
    全站熱搜

    西夏普 發表在 痞客邦 留言(1) 人氣()