- 论坛徽章:
- 59
|
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace CSGraphLinear
- {
- public static class BitmapEx
- {
- public static void ToBlackAndWhite(this Bitmap bitmap)
- {
- }
- }
- public class LinearGraph:IDisposable
- {
- public LinearGraph(int width, int height)
- {
- this._bm = new Bitmap(width, height);
- this._g = Graphics.FromImage(this._bm);
- this._lines = new List<KeyValuePair<System.Windows.Point[], object[]>>();
- this.XAxisLables = new List<KeyValuePair<double, string>>();
- this.YAxisLables = new List<KeyValuePair<double, string>>();
- this._Labels = new List<KeyValuePair<System.Windows.Point, string>>();
- this.Margin = new Rectangle(5, 5, 5, 5);
- this.BackgroundColor = Color.White;
- this.AxisColor = Color.Black;
- this.AxisWidth = 1.0D;
- }
- public void Resize(int width, int height)
- {
- if (width > 0 && height > 0)
- {
- this._g.Dispose();
- this._bm.Dispose();
- this._bm = new Bitmap(width, height);
- this._g = Graphics.FromImage(this._bm);
- this.Draw();
- }
- }
- public void Draw()
- {
- // -- Clear background
- this._g.Clear(this.BackgroundColor);
- // -- Search max/min value of lines points.
- double xMin = double.MaxValue,
- xMax = double.MinValue,
- yMin = double.MaxValue,
- yMax = double.MinValue;
- {
- foreach (var line in this._lines)
- {
- foreach (var pt in line.Key)
- {
- if (pt.X > xMax)
- {
- xMax = pt.X;
- }
- if (pt.X < xMin)
- {
- xMin = pt.X;
- }
- if (pt.Y > yMax)
- {
- yMax = pt.Y;
- }
- if (pt.Y < yMin)
- {
- yMin = pt.Y;
- }
- }//end for each point
- }//end foreach line
- }
- do
- {
- // -- Check the size
- if(this._bm.Width <=this.Margin.Left +this.Margin.Right ||
- this._bm.Height <= this.Margin.Top + this.Margin.Bottom) break;
- // -- Calculate the scale
- double xScale = (this._bm.Width - this.Margin.Left - this.Margin.Right) / (xMax - xMin);
- double yScale = (this._bm.Height - this.Margin.Top - this.Margin.Bottom) / (yMax - yMin);
- // -- Draw XAxis
- using (Pen p = new Pen(this.AxisColor, (float)this.AxisWidth))
- {
- this._g.DrawLine(p, this.Margin.Left, 0, this.Margin.Left, this._bm.Height);
- this._g.DrawLine(p, 0, this._bm.Height - this.Margin.Bottom, this._bm.Width, this._bm.Height - this.Margin.Bottom);
- }
- if(xMax <=xMin ||yMax <=yMin) break;
- // -- Draw scales in X/Y axises
- { const double nAxisSplit =6.0D;
- Func<double, double> ToAlignedStepWidth = delegate(double src)
- {
- double srcCpy = src;
- double rsToAlignedStepWidth;
- double dScale = 1.0D;
- if (srcCpy >= 1.0D)
- {
- while (srcCpy > 1.0D)
- {
- dScale *= 10.0D;
- srcCpy = src / dScale;
- }
- rsToAlignedStepWidth = Math.Ceiling(src / dScale) * dScale;
- if ((rsToAlignedStepWidth - src) / rsToAlignedStepWidth < 0.3D)
- {
- rsToAlignedStepWidth = Math.Floor(src / dScale) * dScale;
- }
- }
- else
- {
- while (srcCpy < 1.0D)
- {
- dScale /= 10.0D;
- srcCpy = src / dScale;
- }
- rsToAlignedStepWidth = Math.Ceiling(src / dScale) * dScale;
- if ((rsToAlignedStepWidth - src) / rsToAlignedStepWidth < 0.3D)
- {
- rsToAlignedStepWidth = Math.Floor(src / dScale) * dScale;
- }
- }
- return rsToAlignedStepWidth;
- };
- double xStepLength = ToAlignedStepWidth((xMax - xMin) / nAxisSplit);
- double yStepLength = ToAlignedStepWidth((yMax - yMin) / nAxisSplit);
- if (xStepLength > xMax - xMin) xStepLength /= 5.0D;
- if ((xMax - xMin) / xStepLength < 3.0D) xStepLength /= 2.0D;
- if (yStepLength > yMax - yMin) yStepLength /= 5.0D;
- if ((yMax - yMin) / yStepLength < 3.0D) yStepLength /= 2.0D;
- // -- Draw X/Y axis scale
- {
- using (Brush br = new SolidBrush(this.AxisColor))
- {
- using (Pen p = new Pen(this.AxisColor))
- {
- { // -- X axis
- int y = this._bm.Height - this.Margin.Bottom;
- for (double xStart = Math.Ceiling(xMin / xStepLength) * xStepLength; xStart < xMax; xStart += xStepLength)
- {
- int x = (int)(xScale * (xStart - xMin) + this.Margin.Left);
- this._g.DrawLine(p, x, y - 1 - (int)this.AxisWidth, x, y + 1);
- if (this.XAxisLables.Count == 0)
- { // -- If the X axis labels specified, not draw the scale
- this._g.DrawString(xStart.ToString(), SystemFonts.DefaultFont, br, new Point(x, y));
- }
- }
- // -- Draw X axis labels
- foreach (var lbl in this.XAxisLables)
- {
- if (!string.IsNullOrWhiteSpace(lbl.Value))
- {
- int x = (int)(xScale * (lbl.Key - xMin) + this.Margin.Left);
- this._g.DrawString(lbl.Value, SystemFonts.DefaultFont, br, new Point(x, y));
- }
- }
- }
- { // -- Y axis
- int x = this.Margin.Left;
- for (double yStart = Math.Ceiling(yMin / yStepLength) * yStepLength; yStart < yMax; yStart += yStepLength)
- {
- int y = this._bm.Height - (int)(yScale * (yStart - yMin) + this.Margin.Bottom);
- this._g.DrawLine(p, x - 1 - (int)this.AxisWidth, y, x + 1, y);
- this._g.DrawString(yStart.ToString(), SystemFonts.DefaultFont, br, new Point(x, y));
- if (IsDrawHorizontalLine)
- {
- using (Pen pVertical = new Pen(this.AxisColor) { DashStyle = DashStyle.Dash })
- {
- this._g.DrawLine(pVertical, x + 1, y, this._bm.Width, y);
- }
- }
- }
- }
- }
- }
- }
- }
- // -- Draw lines
- foreach (var line in this._lines)
- {
- Point[] pts =new Point[line.Key.Length];
- for (int iPt = 0; iPt < line.Key.Length; iPt++)
- {
- int x = (int)(xScale * (line.Key[iPt].X - xMin) + this.Margin.Left);
- int y = this._bm.Height -(int)(yScale * (line.Key[iPt].Y-yMin) + this.Margin.Bottom);
- pts[iPt] = new Point(x,y);
- }
- using (Pen p = new Pen((Color)line.Value[(int)LineStyle.LineColor]) {
- DashStyle = (DashStyle)line.Value[(int)LineStyle.PenStyle],
- Width = (float)Convert.ToDouble(line.Value[(int)LineStyle.LineWidth])
- })
- {
- this._g.DrawLines(p, pts);
- }
- }//end foreach: line
- // -- Draw lables
- using (Brush br = new SolidBrush(this.AxisColor))
- {
- foreach (var kv in this._Labels)
- {
- if (!string.IsNullOrWhiteSpace(kv.Value))
- {
- int x = (int)(xScale * (kv.Key.X - xMin) + this.Margin.Left);
- int y = this._bm.Height - (int)(yScale * (kv.Key.Y - yMin) + this.Margin.Bottom);
- this._g.DrawString(kv.Value, SystemFonts.DefaultFont, br, new Point(x, y));
- }
- }
- }
- }while(false);
- }
- public Rectangle Margin
- {
- set;
- get;
- }
- public Color BackgroundColor
- {
- set;
- get;
- }
- public Color AxisColor
- {
- set;
- get;
- }
- public double AxisWidth
- {
- set;
- get;
- }
- public List<KeyValuePair<double, string>> XAxisLables
- {
- get;
- private set;
- }
- public List<KeyValuePair<double, string>> YAxisLables
- {
- get;
- private set;
- }
- public bool IsDrawHorizontalLine
- {
- set;
- get;
- }
- #region -- Collection functions --
- public void Add(System.Windows.Point[] pts, Color cl, int width, DashStyle style)
- {
- if (pts != null)
- {
- this._lines.Add(
- new KeyValuePair<System.Windows.Point[], object[]>(
- pts,
- new object[] { style, cl, width, }
- )
- );
- }
- }
- public void Add(System.Windows.Point[] pts, Color cl, int width) // Default style is Solid
- {
- this.Add(pts, cl, width, DashStyle.Solid);
- }
- public void Add(System.Windows.Point[] pts, Color cl) // Default width is 1
- {
- this.Add(pts, cl, 1);
- }
- public void Add(System.Windows.Point[] pts) // Default color is black
- {
- this.Add(pts, Color.Black);
- }
- public bool Remove(int idx)
- {
- bool rs = false;
- if (idx >= 0 && this._lines.Count > idx)
- {
- this._lines.RemoveAt(idx);
- rs = true;
- }
- return rs;
- }
- public void Clear()
- {
- this._lines.Clear();
- }
- public void AddLabel(double x, double y, string s){
- this._Labels.Add(new KeyValuePair<System.Windows.Point, string>(new System.Windows.Point(x,y), s));
- }
- public void RemoveLable(int idx)
- {
- if (idx >= 0 && this._Labels.Count > idx)
- {
- this._Labels.RemoveAt(idx);
- }
- }
- public void ClearLabels()
- {
- this._Labels.Clear();
- }
- #endregion -- Collection functions --
- #region -- Helper functions
- public static explicit operator Bitmap(LinearGraph obj)
- {
- Bitmap rsBm = null;
- if (obj != null)
- {
- rsBm = obj._bm;
- }
- return rsBm;
- }
- public void Dispose()
- {
- this._g = null;
- this._bm.Dispose();
- //Pen p =null;
- //p.DashStyle =System.Drawing.Drawing2D.DashStyle.Solid;
- }
- #endregion #region -- Helper functions
- #region private member and defines
- // -- System graphic objects --
- private Graphics _g = null;
- private Bitmap _bm = null;
- // -- Lines --
- private enum LineStyle:int
- {
- PenStyle =0,
- LineColor =1,
- LineWidth =2,
- }
- private List<KeyValuePair<System.Windows.Point[], object[]>> _lines =null;
- private List<KeyValuePair<System.Windows.Point, string>> _Labels = new List<KeyValuePair<System.Windows.Point, string>>();
- #endregion private member and defines
- }
- }
复制代码 |
|