/// <summary> /// 绘制矩形图,根据BarChartType和ds数量确定Bar绘制方式。 /// 当BarChartType为Vertical或Horizontal,且ds数量大于1时,为多组柱图;其余情况为单柱图 /// </summary> /// <param name="dc"></param> /// <param name="g"></param> /// <param name="cs"></param> /// <param name="xa"></param> /// <param name="ya"></param> internal static void AddBars(DataCollectionBar dc, Graphics g, ChartStyle cs, XAxis xa, YAxis ya, Y2Axis y2a) { int numberOfDataSeries = dc.DataSeriesList.Count; //比较各列个数,柱状图需统一个数,以最多个数为准 int nPoints = 0; bool isConsistant = true; bool isY2 = false; foreach (DataSeries ds in dc.DataSeriesList) { if (nPoints < ds.PointList.Count) { nPoints = ds.PointList.Count; } if (ds.IsY2Data) { isY2 = true; } } // Draw bars: ArrayList temp = new ArrayList(); float[] tempy = new float[nPoints]; PointF temppt = new PointF(); int n = 0; foreach (DataSeries ds in dc.DataSeriesList) { Pen aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.LineThickness); aPen.DashStyle = ds.LineStyle.LinePattern; SolidBrush aBrush; if (ds.FillColor != Color.Empty) { aBrush = new SolidBrush(ds.FillColor); } else { aBrush = new SolidBrush(Color.FromArgb(180, ds.LineStyle.LineColor)); } PointF[] pts = new PointF[4]; PointF pt; float width; if (dc.BarChartType == BarChartTypeEnum.Vertical) { if (numberOfDataSeries == 1) { width = (float)xa.XTick * dc.BarWidth; if (!isY2) { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; float x = pt.X - xa.XTick / 2; pts[0] = cs.Point2D(new PointF(x - width / 2, 0), xa, ya); pts[1] = cs.Point2D(new PointF(x + width / 2, 0), xa, ya); pts[2] = cs.Point2D(new PointF(x + width / 2, pt.Y), xa, ya); pts[3] = cs.Point2D(new PointF(x - width / 2, pt.Y), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; float x = pt.X - xa.XTick / 2; pts[0] = cs.Point2DY2(new PointF(x - width / 2, 0), xa, y2a); pts[1] = cs.Point2DY2(new PointF(x + width / 2, 0), xa, y2a); pts[2] = cs.Point2DY2(new PointF(x + width / 2, pt.Y), xa, y2a); pts[3] = cs.Point2DY2(new PointF(x - width / 2, pt.Y), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } } else if (numberOfDataSeries > 1) { //width = 0.7f * (float)xa.XTick; dc.BarWidth = (dc.BarWidth > 0 && dc.BarWidth <= 1) ? dc.BarWidth : 0.95f; width = (float)xa.XTick * dc.BarWidth; if (!isY2) { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; float x = pt.X;// - (float)xa.XTick / 2 float w1 = width / numberOfDataSeries; float w = dc.BarWidth * w1; float space = (w1 - w) / 2; pts[0] = cs.Point2D(new PointF(x - width / 2 + space + n * w1, 0), xa, ya); pts[1] = cs.Point2D(new PointF(x - width / 2 + space + n * w1 + w, 0), xa, ya); pts[2] = cs.Point2D(new PointF(x - width / 2 + space + n * w1 + w, pt.Y), xa, ya); pts[3] = cs.Point2D(new PointF(x - width / 2 + space + n * w1, pt.Y), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; float x = pt.X - (float)xa.XTick / 2; float w1 = width / numberOfDataSeries; float w = dc.BarWidth * w1; float space = (w1 - w) / 2; pts[0] = cs.Point2DY2(new PointF(x - width / 2 + space + n * w1, 0), xa, y2a); pts[1] = cs.Point2DY2(new PointF(x - width / 2 + space + n * w1 + w, 0), xa, y2a); pts[2] = cs.Point2DY2(new PointF(x - width / 2 + space + n * w1 + w, pt.Y), xa, y2a); pts[3] = cs.Point2DY2(new PointF(x - width / 2 + space + n * w1, pt.Y), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } } } else if (dc.BarChartType == BarChartTypeEnum.VerticalOverlay && numberOfDataSeries > 1) { width = (float)xa.XTick * dc.BarWidth; width = width / (float)Math.Pow(2, n); if (!isY2) { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; float x = pt.X - xa.XTick / 2; pts[0] = cs.Point2D(new PointF(x - width / 2, 0), xa, ya); pts[1] = cs.Point2D(new PointF(x + width / 2, 0), xa, ya); pts[2] = cs.Point2D(new PointF(x + width / 2, pt.Y), xa, ya); pts[3] = cs.Point2D(new PointF(x - width / 2, pt.Y), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; float x = pt.X - xa.XTick / 2; pts[0] = cs.Point2DY2(new PointF(x - width / 2, 0), xa, y2a); pts[1] = cs.Point2DY2(new PointF(x + width / 2, 0), xa, y2a); pts[2] = cs.Point2DY2(new PointF(x + width / 2, pt.Y), xa, y2a); pts[3] = cs.Point2DY2(new PointF(x - width / 2, pt.Y), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } } else if (dc.BarChartType == BarChartTypeEnum.VerticalStack && numberOfDataSeries > 1) { width = xa.XTick * dc.BarWidth; if (!isY2) { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; if (temp.Count > 0) { tempy[i] = tempy[i] + ((PointF)temp[i]).Y; } float x = pt.X - xa.XTick / 2; pts[0] = cs.Point2D(new PointF(x - width / 2, 0 + tempy[i]), xa, ya); pts[1] = cs.Point2D(new PointF(x + width / 2, 0 + tempy[i]), xa, ya); pts[2] = cs.Point2D(new PointF(x + width / 2, pt.Y + tempy[i]), xa, ya); pts[3] = cs.Point2D(new PointF(x - width / 2, pt.Y + tempy[i]), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; if (temp.Count > 0) { tempy[i] = tempy[i] + ((PointF)temp[i]).Y; } float x = pt.X - xa.XTick / 2; pts[0] = cs.Point2DY2(new PointF(x - width / 2, 0 + tempy[i]), xa, y2a); pts[1] = cs.Point2DY2(new PointF(x + width / 2, 0 + tempy[i]), xa, y2a); pts[2] = cs.Point2DY2(new PointF(x + width / 2, pt.Y + tempy[i]), xa, y2a); pts[3] = cs.Point2DY2(new PointF(x - width / 2, pt.Y + tempy[i]), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } temp = ds.PointList; } else if (dc.BarChartType == BarChartTypeEnum.Horizontal) { if (numberOfDataSeries == 1) { if (!isY2) { width = ya.YTick * dc.BarWidth; for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); float y = pt.Y - ya.YTick / 2; pts[0] = cs.Point2D(new PointF(0, y - width / 2), xa, ya); pts[1] = cs.Point2D(new PointF(0, y + width / 2), xa, ya); pts[2] = cs.Point2D(new PointF(pt.X, y + width / 2), xa, ya); pts[3] = cs.Point2D(new PointF(pt.X, y - width / 2), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { width = y2a.Y2Tick * dc.BarWidth; for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); float y = pt.Y - y2a.Y2Tick / 2; pts[0] = cs.Point2DY2(new PointF(0, y - width / 2), xa, y2a); pts[1] = cs.Point2DY2(new PointF(0, y + width / 2), xa, y2a); pts[2] = cs.Point2DY2(new PointF(pt.X, y + width / 2), xa, y2a); pts[3] = cs.Point2DY2(new PointF(pt.X, y - width / 2), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } } else if (numberOfDataSeries > 1) { //width = 0.7f * ya.YTick; dc.BarWidth = (dc.BarWidth > 0 && dc.BarWidth <= 1) ? dc.BarWidth : 0.95f; if (!isY2) { width = (float)ya.YTick * dc.BarWidth; for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); float w1 = width / numberOfDataSeries; float w = dc.BarWidth * w1; float space = (w1 - w) / 2; float y = pt.Y - ya.YTick / 2; pts[0] = cs.Point2D(new PointF(0, y - width / 2 + space + n * w1), xa, ya); pts[1] = cs.Point2D(new PointF(0, y - width / 2 + space + n * w1 + w), xa, ya); pts[2] = cs.Point2D(new PointF(pt.X, y - width / 2 + space + n * w1 + w), xa, ya); pts[3] = cs.Point2D(new PointF(pt.X, y - width / 2 + space + n * w1), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { width = (float)y2a.Y2Tick * dc.BarWidth; for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); float w1 = width / numberOfDataSeries; float w = dc.BarWidth * w1; float space = (w1 - w) / 2; float y = pt.Y - y2a.Y2Tick / 2; pts[0] = cs.Point2DY2(new PointF(0, y - width / 2 + space + n * w1), xa, y2a); pts[1] = cs.Point2DY2(new PointF(0, y - width / 2 + space + n * w1 + w), xa, y2a); pts[2] = cs.Point2DY2(new PointF(pt.X, y - width / 2 + space + n * w1 + w), xa, y2a); pts[3] = cs.Point2DY2(new PointF(pt.X, y - width / 2 + space + n * w1), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } } } else if (dc.BarChartType == BarChartTypeEnum.HorizontalOverlay && numberOfDataSeries > 1) { if (!isY2) { width = ya.YTick * dc.BarWidth; width = width / (float)Math.Pow(2, n); for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); float y = pt.Y - ya.YTick / 2; pts[0] = cs.Point2D(new PointF(0, y - width / 2), xa, ya); pts[1] = cs.Point2D(new PointF(0, y + width / 2), xa, ya); pts[2] = cs.Point2D(new PointF(pt.X, y + width / 2), xa, ya); pts[3] = cs.Point2D(new PointF(pt.X, y - width / 2), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { width = y2a.Y2Tick * dc.BarWidth; width = width / (float)Math.Pow(2, n); for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); float y = pt.Y - y2a.Y2Tick / 2; pts[0] = cs.Point2DY2(new PointF(0, y - width / 2), xa, y2a); pts[1] = cs.Point2DY2(new PointF(0, y + width / 2), xa, y2a); pts[2] = cs.Point2DY2(new PointF(pt.X, y + width / 2), xa, y2a); pts[3] = cs.Point2DY2(new PointF(pt.X, y - width / 2), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } } else if (dc.BarChartType == BarChartTypeEnum.HorizontalStack && numberOfDataSeries > 1) { if (!isY2) { width = ya.YTick * dc.BarWidth; for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); if (temp.Count > 0) { temppt = (PointF)temp[i]; tempy[i] = tempy[i] + temppt.Y; } float y = pt.Y - ya.YTick / 2; pts[0] = cs.Point2D(new PointF(0 + tempy[i], y - width / 2), xa, ya); pts[1] = cs.Point2D(new PointF(0 + tempy[i], y + width / 2), xa, ya); pts[2] = cs.Point2D(new PointF(pt.X + tempy[i], y + width / 2), xa, ya); pts[3] = cs.Point2D(new PointF(pt.X + tempy[i], y - width / 2), xa, ya); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } else { width = y2a.Y2Tick * dc.BarWidth; for (int i = 0; i < ds.PointList.Count; i++) { temppt = (PointF)ds.PointList[i]; pt = new PointF(temppt.Y, temppt.X); if (temp.Count > 0) { temppt = (PointF)temp[i]; tempy[i] = tempy[i] + temppt.Y; } float y = pt.Y - y2a.Y2Tick / 2; pts[0] = cs.Point2DY2(new PointF(0 + tempy[i], y - width / 2), xa, y2a); pts[1] = cs.Point2DY2(new PointF(0 + tempy[i], y + width / 2), xa, y2a); pts[2] = cs.Point2DY2(new PointF(pt.X + tempy[i], y + width / 2), xa, y2a); pts[3] = cs.Point2DY2(new PointF(pt.X + tempy[i], y - width / 2), xa, y2a); g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } } } temp = ds.PointList; } n++; aPen.Dispose(); aBrush.Dispose(); } }
internal static void AddAreas(DataCollectionArea dc, Graphics g, ChartStyle cs, XAxis xa, YAxis ya, Y2Axis y2a) { if (dc.ChartType != Chart2DTypeEnum.AreaChart || dc.DataSeriesList.Count == 0) { return; } //比较各列点数,面积图需统一点数(暂不处理,待优化:以最少点数为准) int nPoints = 0; bool isConsistant = true; bool isY2 = false; foreach (DataSeries ds in dc.DataSeriesList) { if (nPoints == 0) { nPoints = ds.PointList.Count; } else if (nPoints != ds.PointList.Count) { isConsistant = false; } if (ds.IsY2Data) { isY2 = true; } } if (!isConsistant) { return; } float[] ySum = new float[nPoints]; PointF[] pts = new PointF[2 * nPoints]; PointF[] pt0 = new PointF[nPoints]; PointF[] pt1 = new PointF[nPoints]; for (int i = 0; i < nPoints; i++) { ySum[i] = dc.AreaAxis; } int n = 0; Pen aPen = new Pen(Color.Black); SolidBrush aBrush = new SolidBrush(Color.Black); foreach (DataSeries ds in dc.DataSeriesList) { //Color fillColor = Color.FromArgb(dc.CMap[n, 0], dc.CMap[n, 1], dc.CMap[n, 2], dc.CMap[n, 3]); if (ds.FillColor != Color.Empty) { aBrush = new SolidBrush(ds.FillColor); } else { aBrush = new SolidBrush(Color.FromArgb(180, ds.LineStyle.LineColor)); } aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.LineThickness); aPen.DashStyle = ds.LineStyle.LinePattern; // Draw lines and areas: if (dc.AreaChartType == AreaChartTypeEnum.Area) { if (!isY2) { for (int i = 0; i < nPoints; i++) { pt0[i] = new PointF(((PointF)ds.PointList[i]).X, ySum[i]); ySum[i] = ySum[i] + ((PointF)ds.PointList[i]).Y; pt1[i] = new PointF(((PointF)ds.PointList[i]).X, ySum[i]); pts[i] = cs.Point2D(pt0[i], xa, ya); pts[2 * nPoints - 1 - i] = cs.Point2D(pt1[i], xa, ya); } } else { for (int i = 0; i < nPoints; i++) { pt0[i] = new PointF(((PointF)ds.PointList[i]).X, ySum[i]); ySum[i] = ySum[i] + ((PointF)ds.PointList[i]).Y; pt1[i] = new PointF(((PointF)ds.PointList[i]).X, ySum[i]); pts[i] = cs.Point2DY2(pt0[i], xa, y2a); pts[2 * nPoints - 1 - i] = cs.Point2DY2(pt1[i], xa, y2a); } } g.FillPolygon(aBrush, pts); if (ds.LineStyle.IsVisible) { g.DrawPolygon(aPen, pts); } n++; } } aPen.Dispose(); aBrush.Dispose(); }
//绘制线性图 internal static void AddLines(DataCollection dc, Graphics g, ChartStyle cs, XAxis xa, YAxis ya, Y2Axis y2a) { if (dc.ChartType != Chart2DTypeEnum.LineChart || dc.DataSeriesList.Count == 0) { return; } //SeriesColor.SetSeriesColor(dc); // Plot lines: foreach (DataSeries ds in dc.DataSeriesList) { if (ds.LineStyle.IsVisible == true) { PointF pt = new PointF(); PointF pt0 = new PointF(); Pen aPen = new Pen(ds.LineStyle.LineColor, ds.LineStyle.LineThickness); aPen.DashStyle = ds.LineStyle.LinePattern; #region line // Plot Line: if (ds.LineChartType == LineChartTypeEnum.Line) { for (int i = 1; i < ds.PointList.Count; i++) { if (!ds.IsY2Data) { g.DrawLine(aPen, cs.Point2D((PointF)ds.PointList[i - 1], xa, ya), cs.Point2D((PointF)ds.PointList[i], xa, ya)); } else { g.DrawLine(aPen, cs.Point2DY2((PointF)ds.PointList[i - 1], xa, y2a), cs.Point2DY2((PointF)ds.PointList[i], xa, y2a)); } } } // Plot Spline: else if (ds.LineChartType == LineChartTypeEnum.Spline) { PointF[] pts = new PointF[ds.PointList.Count]; for (int i = 0; i < pts.Length; i++) { if (!ds.IsY2Data) { pts[i] = cs.Point2D((PointF)(ds.PointList[i]), xa, ya); } else { pts[i] = cs.Point2DY2((PointF)(ds.PointList[i]), xa, y2a); } } g.DrawCurve(aPen, pts); } #endregion #region Stairstep // Plot Stairstep: else if (ds.LineChartType == LineChartTypeEnum.StairStep) { ArrayList aList = new ArrayList(); if (!ds.IsY2Data) { // Create Stairstep data: for (int i = 0; i < ds.PointList.Count - 1; i++) { pt = (PointF)ds.PointList[i]; pt0 = (PointF)ds.PointList[i + 1]; aList.Add(pt); aList.Add(new PointF(pt0.X, pt.Y)); } aList.Add(ds.PointList[ds.PointList.Count - 1]); // Draw stairstep chart: for (int i = 1; i < aList.Count; i++) { g.DrawLine(aPen, cs.Point2D((PointF)aList[i - 1], xa, ya), cs.Point2D((PointF)aList[i], xa, ya)); } } else { for (int i = 0; i < ds.PointList.Count - 1; i++) { pt = (PointF)ds.PointList[i]; pt0 = (PointF)ds.PointList[i + 1]; aList.Add(pt); aList.Add(new PointF(pt0.X, pt.Y)); } aList.Add(ds.PointList[ds.PointList.Count - 1]); for (int i = 1; i < aList.Count; i++) { g.DrawLine(aPen, cs.Point2DY2((PointF)aList[i - 1], xa, y2a), cs.Point2DY2((PointF)aList[i], xa, y2a)); } } } #endregion #region Stem // Plot Stems: else if (ds.LineChartType == LineChartTypeEnum.Stem) { if (!ds.IsY2Data) { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; pt0 = new PointF(pt.X, 0); g.DrawLine(aPen, cs.Point2D(pt0, xa, ya), cs.Point2D(pt, xa, ya)); } } else { for (int i = 0; i < ds.PointList.Count; i++) { pt = (PointF)ds.PointList[i]; pt0 = new PointF(pt.X, 0); g.DrawLine(aPen, cs.Point2DY2(pt0, xa, y2a), cs.Point2DY2(pt, xa, y2a)); } } } #endregion #region ErrorBar //Plot ErrorBar else if (ds.LineChartType == LineChartTypeEnum.ErrorBar) { Pen errorPen = new Pen(ds.ErrorLineStyle.LineColor, ds.ErrorLineStyle.LineThickness); errorPen.DashStyle = ds.ErrorLineStyle.LinePattern; float barLength = 0; if (!ds.IsY2Data) { // Draw lines: for (int i = 1; i < ds.PointList.Count; i++) { pt0 = (PointF)ds.PointList[i - 1]; pt = (PointF)ds.PointList[i]; g.DrawLine(aPen, cs.Point2D(pt0, xa, ya), cs.Point2D(pt, xa, ya)); barLength = (pt.X - pt0.X) / 4; } // Draw error lines: for (int i = 0; i < ds.ErrorList.Count; i++) { PointF errorPoint = (PointF)ds.ErrorList[i]; PointF linePoint = (PointF)ds.PointList[i]; pt0 = new PointF(linePoint.X, linePoint.Y - errorPoint.Y / 2); pt = new PointF(linePoint.X, linePoint.Y + errorPoint.Y / 2); g.DrawLine(errorPen, cs.Point2D(pt0, xa, ya), cs.Point2D(pt, xa, ya)); PointF pt1 = new PointF(pt0.X - barLength / 2, pt0.Y); PointF pt2 = new PointF(pt0.X + barLength / 2, pt0.Y); g.DrawLine(errorPen, cs.Point2D(pt1, xa, ya), cs.Point2D(pt2, xa, ya)); pt1 = new PointF(pt.X - barLength / 2, pt.Y); pt2 = new PointF(pt.X + barLength / 2, pt.Y); g.DrawLine(errorPen, cs.Point2D(pt1, xa, ya), cs.Point2D(pt2, xa, ya)); } } else { for (int i = 1; i < ds.PointList.Count; i++) { pt0 = (PointF)ds.PointList[i - 1]; pt = (PointF)ds.PointList[i]; g.DrawLine(aPen, cs.Point2DY2(pt0, xa, y2a), cs.Point2DY2(pt, xa, y2a)); barLength = (pt.X - pt0.X) / 4; } for (int i = 0; i < ds.ErrorList.Count; i++) { PointF errorPoint = (PointF)ds.ErrorList[i]; PointF linePoint = (PointF)ds.PointList[i]; pt0 = new PointF(linePoint.X, linePoint.Y - errorPoint.Y / 2); pt = new PointF(linePoint.X, linePoint.Y + errorPoint.Y / 2); g.DrawLine(errorPen, cs.Point2DY2(pt0, xa, y2a), cs.Point2DY2(pt, xa, y2a)); PointF pt1 = new PointF(pt0.X - barLength / 2, pt0.Y); PointF pt2 = new PointF(pt0.X + barLength / 2, pt0.Y); g.DrawLine(errorPen, cs.Point2DY2(pt1, xa, y2a), cs.Point2DY2(pt2, xa, y2a)); pt1 = new PointF(pt.X - barLength / 2, pt.Y); pt2 = new PointF(pt.X + barLength / 2, pt.Y); g.DrawLine(errorPen, cs.Point2DY2(pt1, xa, y2a), cs.Point2DY2(pt2, xa, y2a)); } } errorPen.Dispose(); } #endregion #region Stock else if ((ds.LineChartType == LineChartTypeEnum.HiLo || ds.LineChartType == LineChartTypeEnum.HiLoOpenClose || ds.LineChartType == LineChartTypeEnum.Candle) && ds.DataString != null) { SolidBrush aBrush = new SolidBrush(ds.LineStyle.LineColor); SolidBrush whiteBrush = new SolidBrush(Color.White); float barLength = cs.PlotArea.Width / (5 * ds.DataString.GetLength(1)); for (int i = 0; i < ds.DataString.GetLength(1); i++) { float[] stockdata = new float[4]; for (int j = 0; j < stockdata.Length; j++) { stockdata[j] = Convert.ToSingle(ds.DataString[j + 1, i]); } PointF ptHigh, ptLow, ptOpen, ptCLose; if (!ds.IsY2Data) { ptHigh = cs.Point2D(new PointF(i, stockdata[1]), xa, ya); ptLow = cs.Point2D(new PointF(i, stockdata[2]), xa, ya); ptOpen = cs.Point2D(new PointF(i, stockdata[0]), xa, ya); ptCLose = cs.Point2D(new PointF(i, stockdata[3]), xa, ya); } else { ptHigh = cs.Point2DY2(new PointF(i, stockdata[1]), xa, y2a); ptLow = cs.Point2DY2(new PointF(i, stockdata[2]), xa, y2a); ptOpen = cs.Point2DY2(new PointF(i, stockdata[0]), xa, y2a); ptCLose = cs.Point2DY2(new PointF(i, stockdata[3]), xa, y2a); } PointF ptOpen1 = new PointF(ptOpen.X - barLength, ptOpen.Y); PointF ptClose1 = new PointF(ptCLose.X + barLength, ptCLose.Y); PointF ptOpen2 = new PointF(ptOpen.X + barLength, ptOpen.Y); PointF ptClose2 = new PointF(ptCLose.X - barLength, ptCLose.Y); // Draw Hi-Lo stock chart: if (ds.LineChartType == LineChartTypeEnum.HiLo) { g.DrawLine(aPen, ptHigh, ptLow); } // Draw Hi-Li-Open-Close chart: else if (ds.LineChartType == LineChartTypeEnum.HiLoOpenClose) { g.DrawLine(aPen, ptHigh, ptLow); g.DrawLine(aPen, ptOpen, ptOpen1); g.DrawLine(aPen, ptCLose, ptClose1); } // Draw candle chart: else if (ds.LineChartType == LineChartTypeEnum.Candle) { PointF[] pts = new PointF[4]; pts[0] = ptOpen1; pts[1] = ptOpen2; pts[2] = ptClose1; pts[3] = ptClose2; g.DrawLine(aPen, ptHigh, ptLow); if (stockdata[0] > stockdata[3]) { g.FillPolygon(aBrush, pts); } else if (stockdata[0] < stockdata[3]) { g.FillPolygon(whiteBrush, pts); } g.DrawPolygon(aPen, pts); } } aBrush.Dispose(); whiteBrush.Dispose(); } #endregion aPen.Dispose(); } } // Plot Symbols: foreach (DataSeries ds in dc.DataSeriesList) { if (ds.LineChartType != LineChartTypeEnum.HiLo && ds.LineChartType != LineChartTypeEnum.HiLoOpenClose && ds.LineChartType != LineChartTypeEnum.Candle) { for (int i = 0; i < ds.PointList.Count; i++) { PointF pt = (PointF)ds.PointList[i]; if (!ds.IsY2Data) { if (pt.X >= xa.XLimMin && pt.X <= xa.XLimMax && pt.Y >= ya.YLimMin && pt.Y <= ya.YLimMax) { ds.SymbolStyle.DrawSymbol(g, cs.Point2D((PointF)ds.PointList[i], xa, ya)); } } else { if (pt.X >= xa.XLimMin && pt.X <= xa.XLimMax && pt.Y >= y2a.Y2LimMin && pt.Y <= y2a.Y2LimMax) { ds.SymbolStyle.DrawSymbol(g, cs.Point2DY2((PointF)ds.PointList[i], xa, y2a)); } } } } } }