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; }
圖例
文章標籤
全站熱搜