public void Draw(FastChart owner, PaintEventArgs e, Point o, Point tip, int width) { var lineCl = LineColor.HasValue ? LineColor.Value : Color.Black; var start = !AlwaysShowNil ? MinValue : new Cortege2 <double, DateTime>(0, DateTime.MinValue); var step = CalculateStep(start, o, tip); if (step.a == 0 && step.b == TimeSpan.Zero) { // нет делений return; } var lblFmt = DeriveFormatFromStep(step); var cur = start; // сместить текущую отметку на ближ. целое значение шага if (!IsDateTime) { cur.a = ((int)(cur.a / step.a)) * step.a; } var drawFormat = new StringFormat(VerticalText ? StringFormatFlags.DirectionVertical : StringFormatFlags.NoWrap); var lenPx = Direction == FastAxisDirection.X ? Math.Abs(tip.X - o.X) : Math.Abs(tip.Y - o.Y); using (var brush = new SolidBrush(lineCl)) { using (var pen = new Pen(lineCl)) { e.Graphics.DrawLine(pen, o.X, o.Y, tip.X, tip.Y); using (var penGridMain = new Pen(ColorMainGrid.HasValue ? ColorMainGrid.Value : Color.DarkGray)) { while (true) { // след. значение if (!IsDateTime) { if (step.a == 0) { break; } cur.a += step.a; } else { if (step.b == TimeSpan.Zero) { break; } cur.b += step.b; } // вышли за пределы шкалы? if (!IsDateTime) { if (cur.a > MaxValue.a) { break; } } if (IsDateTime) { if (cur.b > MaxValue.b) { break; } } // текст подписи var labelTxt = !IsDateTime ? cur.a.ToString(lblFmt) : cur.b.ToString(lblFmt); // размеры, занимаемые подписью var txtSzOrig = e.Graphics.MeasureString(labelTxt, owner.Font); var txtSz = VerticalText ? new SizeF(txtSzOrig.Height, txtSzOrig.Width) : txtSzOrig; // координата var ptDist = !IsDateTime ? (cur.a - start.a) / (MaxValue.a - start.a) : (cur.b - start.b).TotalMilliseconds / (MaxValue.b - start.b).TotalMilliseconds; ptDist *= lenPx; var ptDot = Direction == FastAxisDirection.X ? new Point(o.X + (int)ptDist, o.Y) : new Point(o.X, o.Y - (int)ptDist); var ptLeftUp = Direction == FastAxisDirection.X ? new PointF(ptDot.X - txtSz.Width / 2, ptDot.Y + 3) : new PointF(ptDot.X - txtSz.Width - 3, ptDot.Y - txtSz.Height / 2); // нарисовать текст e.Graphics.DrawString(labelTxt, owner.Font, brush, ptLeftUp.X, ptLeftUp.Y, drawFormat); // нарисовать засечку try { if (Direction == FastAxisDirection.X) { e.Graphics.DrawLine(pen, ptDot.X, ptDot.Y - 2, ptDot.X, ptDot.Y + 2); } else { e.Graphics.DrawLine(pen, ptDot.X - 2, ptDot.Y, ptDot.X + 2, ptDot.Y); } } catch (Exception ex) { owner.lastError = ex.ToString(); return; } // нарисовать сетку if (DrawMainGrid) { if (Direction == FastAxisDirection.X) { e.Graphics.DrawLine(penGridMain, ptDot.X, ptDot.Y + 2, ptDot.X, ptDot.Y - width); } else { e.Graphics.DrawLine(penGridMain, ptDot.X + 2, ptDot.Y, ptDot.X + width, ptDot.Y); } } }// while // нарисовать рамку if (DrawMainGrid) { if (Direction == FastAxisDirection.X) { e.Graphics.DrawLine(penGridMain, o.X, o.Y - width, tip.X, o.Y - width); } else { e.Graphics.DrawLine(penGridMain, o.X + width, o.Y, o.X + width, tip.Y); } } } // main grid pen } // brush } }
private void RenderChart(StringBuilder sb, string title, int width, int height, List <List <FastSeriesPoint> > series, List <string> seriesNames) { var seriesColors = new [] { Color.DarkBlue, Color.DarkOliveGreen, Color.Firebrick }; var needYearsInFormat = stat.listEquity[stat.listEquity.Count - 1].time.Year != stat.listEquity[0].time.Year; var formatString = needYearsInFormat ? "dd.MM.yyyy" : "dd MMM"; var chart = new FastChart.Chart.FastChart { ShowLegend = series.Count > 1, LegendPlacement = FastChart.Chart.FastChart.ChartLegendPlacement.Справа, BorderStyle = BorderStyle.None, DrawMargin = false }; var axisX = new FastAxis(FastAxisDirection.X, true) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, LabelFormat = formatString }; // границы оси Y var min = double.MaxValue; var max = double.MinValue; foreach (var ser in series) { foreach (var pt in ser) { if (min > pt.y) { min = pt.y; } if (max < pt.y) { max = pt.y; } } } min = GetLowerBound(min); var axisY = new FastAxis(FastAxisDirection.Y, false) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, AutoScale100 = false, MinValue = new FastChart.Chart.Cortege2 <double, DateTime>(min, default(DateTime)), MaxValue = new FastChart.Chart.Cortege2 <double, DateTime>(max * 1.05, default(DateTime)) }; chart.Axes.Add(axisX); chart.Axes.Add(axisY); // добавить серии и точки for (var i = 0; i < series.Count; i++) { var ser = new FastSeries(seriesNames[i], FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(seriesColors[i], 2f), AntiAlias = true }; ser.points.AddRange(series[i]); chart.series.Add(ser); } chart.Width = width; chart.Height = height; // рендерить чарт в картинку var img = new Bitmap(width, height); chart.DrawToBitmap(img, new Rectangle(0, 0, width - 1, height - 1)); // включить картинку в HTML var str = BaseWebServer.MakeEmbeddedPictureString(img); var imgStr = string.Format( "<img src=\"{0}\" alt=\"Доходность по счету\" style=\"cursor:pointer\" /> ", str); sb.AppendLine("<br/>"); sb.AppendLine(imgStr); sb.AppendLine(string.Format(" <p style=\"font-weight:bold\">{0}</p>", title)); }
public void Draw(FastChart owner, PaintEventArgs e, Point o, Point tip, int width) { var lineCl = LineColor.HasValue ? LineColor.Value : Color.Black; var start = !AlwaysShowNil ? MinValue : new Cortege2<double, DateTime>(0, DateTime.MinValue); var step = CalculateStep(start, o, tip); if (step.a == 0 && step.b == TimeSpan.Zero) // нет делений return; var lblFmt = DeriveFormatFromStep(step); var cur = start; // сместить текущую отметку на ближ. целое значение шага if (!IsDateTime) { cur.a = ((int)(cur.a / step.a)) * step.a; } var drawFormat = new StringFormat(VerticalText ? StringFormatFlags.DirectionVertical : StringFormatFlags.NoWrap); var lenPx = Direction == FastAxisDirection.X ? Math.Abs(tip.X - o.X) : Math.Abs(tip.Y - o.Y); using (var brush = new SolidBrush(lineCl)) { using (var pen = new Pen(lineCl)) { e.Graphics.DrawLine(pen, o.X, o.Y, tip.X, tip.Y); using (var penGridMain = new Pen(ColorMainGrid.HasValue ? ColorMainGrid.Value : Color.DarkGray)) { while (true) { // след. значение if (!IsDateTime) { if (step.a == 0) break; cur.a += step.a; } else { if (step.b == TimeSpan.Zero) break; cur.b += step.b; } // вышли за пределы шкалы? if (!IsDateTime) if (cur.a > MaxValue.a) break; if (IsDateTime) if (cur.b > MaxValue.b) break; // текст подписи var labelTxt = !IsDateTime ? cur.a.ToString(lblFmt) : cur.b.ToString(lblFmt); // размеры, занимаемые подписью var txtSzOrig = e.Graphics.MeasureString(labelTxt, owner.Font); var txtSz = VerticalText ? new SizeF(txtSzOrig.Height, txtSzOrig.Width) : txtSzOrig; // координата var ptDist = !IsDateTime ? (cur.a - start.a)/(MaxValue.a - start.a) : (cur.b - start.b).TotalMilliseconds/ (MaxValue.b - start.b).TotalMilliseconds; ptDist *= lenPx; var ptDot = Direction == FastAxisDirection.X ? new Point(o.X + (int) ptDist, o.Y) : new Point(o.X, o.Y - (int) ptDist); var ptLeftUp = Direction == FastAxisDirection.X ? new PointF(ptDot.X - txtSz.Width/2, ptDot.Y + 3) : new PointF(ptDot.X - txtSz.Width - 3, ptDot.Y - txtSz.Height/2); // нарисовать текст e.Graphics.DrawString(labelTxt, owner.Font, brush, ptLeftUp.X, ptLeftUp.Y, drawFormat); // нарисовать засечку try { if (Direction == FastAxisDirection.X) e.Graphics.DrawLine(pen, ptDot.X, ptDot.Y - 2, ptDot.X, ptDot.Y + 2); else e.Graphics.DrawLine(pen, ptDot.X - 2, ptDot.Y, ptDot.X + 2, ptDot.Y); } catch (Exception ex) { owner.lastError = ex.ToString(); return; } // нарисовать сетку if (DrawMainGrid) { if (Direction == FastAxisDirection.X) e.Graphics.DrawLine(penGridMain, ptDot.X, ptDot.Y + 2, ptDot.X, ptDot.Y - width); else e.Graphics.DrawLine(penGridMain, ptDot.X + 2, ptDot.Y, ptDot.X + width, ptDot.Y); } }// while // нарисовать рамку if (DrawMainGrid) { if (Direction == FastAxisDirection.X) e.Graphics.DrawLine(penGridMain, o.X, o.Y - width, tip.X, o.Y - width); else e.Graphics.DrawLine(penGridMain, o.X + width, o.Y, o.X + width, tip.Y); } }// main grid pen }// brush } }
/// <summary> /// вернуть полный путь к файлу с картинкой доходности /// </summary> private string MakeProfitChart(string tempFolder, Size chartSize) { var chart = new FastChart.Chart.FastChart { ShowLegend = true, LegendPlacement = FastChart.Chart.FastChart.ChartLegendPlacement.Справа, BorderStyle = BorderStyle.None, DrawMargin = false }; var axisX = new FastAxis(FastAxisDirection.X, true) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, Step = new FastChart.Chart.Cortege2 <double, TimeSpan>(0, new TimeSpan(356, 0, 0, 0)), LabelFormat = "yyyy" }; var maxProfit = (double)profitDic.Max(p => p.equity); var axisY = new FastAxis(FastAxisDirection.Y, false) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, AutoScale100 = false, MinValue = new FastChart.Chart.Cortege2 <double, DateTime>(0, default(DateTime)), MaxValue = new FastChart.Chart.Cortege2 <double, DateTime>(maxProfit * 1.1, default(DateTime)) }; if (maxProfit > 1000) { var stepSize = maxProfit < 2000 ? 200 : maxProfit < 4000 ? 500 : 1000; axisY.Step = new FastChart.Chart.Cortege2 <double, TimeSpan>(stepSize, default(TimeSpan)); } chart.Axes.Add(axisX); chart.Axes.Add(axisY); var seriesFund = new FastSeries("УК", FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(Color.FromArgb(80, 5, 5), 2f), AntiAlias = true }; seriesFund.points.AddRange(profitDic.Select(p => new FastSeriesPoint(p.time, p.equity)).ToList()); chart.series.Add(seriesFund); // серии бенчмарков var seriesBmA = new FastSeries(benchmarkA, FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(Color.FromArgb(5, 80, 5), 2f), AntiAlias = true }; var seriesBmB = new FastSeries(benchmarkB, FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(Color.FromArgb(5, 5, 80), 2f), AntiAlias = true }; seriesBmA.points.AddRange(MakeBenchmarkProfit1000Points(vamiBenchmarkA)); seriesBmB.points.AddRange(MakeBenchmarkProfit1000Points(vamiBenchmarkB)); chart.series.Add(seriesBmA); chart.series.Add(seriesBmB); chart.Width = chartSize.Width; chart.Height = chartSize.Height; var img = new Bitmap(chartSize.Width, chartSize.Height); chart.DrawToBitmap(img, new Rectangle(0, 0, chartSize.Width, chartSize.Height)); var path = string.Format("{0}\\chartProfit1000_{1}.png", tempFolder, DateTime.Now.Millisecond); img.Save(path, ImageFormat.Png); return(path); }
private void RenderChart(StringBuilder sb, string title, int width, int height, List<List<FastSeriesPoint>> series, List<string> seriesNames) { var seriesColors = new [] {Color.DarkBlue, Color.DarkOliveGreen, Color.Firebrick}; var needYearsInFormat = stat.listEquity[stat.listEquity.Count - 1].time.Year != stat.listEquity[0].time.Year; var formatString = needYearsInFormat ? "dd.MM.yyyy" : "dd MMM"; var chart = new FastChart.Chart.FastChart { ShowLegend = series.Count > 1, LegendPlacement = FastChart.Chart.FastChart.ChartLegendPlacement.Справа, BorderStyle = BorderStyle.None, DrawMargin = false }; var axisX = new FastAxis(FastAxisDirection.X, true) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, LabelFormat = formatString }; // границы оси Y var min = double.MaxValue; var max = double.MinValue; foreach (var ser in series) { foreach (var pt in ser) { if (min > pt.y) min = pt.y; if (max < pt.y) max = pt.y; } } min = GetLowerBound(min); var axisY = new FastAxis(FastAxisDirection.Y, false) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, AutoScale100 = false, MinValue = new FastChart.Chart.Cortege2<double, DateTime>(min, default(DateTime)), MaxValue = new FastChart.Chart.Cortege2<double, DateTime>(max * 1.05, default(DateTime)) }; chart.Axes.Add(axisX); chart.Axes.Add(axisY); // добавить серии и точки for (var i = 0; i < series.Count; i++) { var ser = new FastSeries(seriesNames[i], FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(seriesColors[i], 2f), AntiAlias = true }; ser.points.AddRange(series[i]); chart.series.Add(ser); } chart.Width = width; chart.Height = height; // рендерить чарт в картинку var img = new Bitmap(width, height); chart.DrawToBitmap(img, new Rectangle(0, 0, width - 1, height - 1)); // включить картинку в HTML var str = BaseWebServer.MakeEmbeddedPictureString(img); var imgStr = string.Format( "<img src=\"{0}\" alt=\"Доходность по счету\" style=\"cursor:pointer\" /> ", str); sb.AppendLine("<br/>"); sb.AppendLine(imgStr); sb.AppendLine(string.Format(" <p style=\"font-weight:bold\">{0}</p>", title)); }
public void ApplyToChart(FastChart chart) { chart.Padding = Padding; chart.DrawMargin = DrawMargin; if (PenMargin != null) chart.penMargin = PenMargin; if (BrushArea != null) chart.brushArea = BrushArea; chart.UseGradient = UseGradient; chart.ClGradStart = ClGradStart; chart.ClGradEnd = ClGradEnd; chart.GradAngle = GradAngle; if (ChartFont != null) chart.Font = ChartFont; if (ColorAxes.Length > 0) { var clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.X)) { if (ax.LineColor.HasValue) continue; ax.LineColor = ColorAxes[clIndex++]; if (clIndex >= ColorAxes.Length) clIndex = 0; } clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.Y)) { if (ax.LineColor.HasValue) continue; ax.LineColor = ColorAxes[clIndex++]; if (clIndex >= ColorAxes.Length) clIndex = 0; } } if (ColorAxesGrids.Length > 0) { var clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.X)) { if (ax.ColorMainGrid.HasValue) continue; ax.ColorMainGrid = ColorAxesGrids[clIndex++]; if (clIndex >= ColorAxesGrids.Length) clIndex = 0; } clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.Y)) { if (ax.ColorMainGrid.HasValue) continue; ax.ColorMainGrid = ColorAxesGrids[clIndex++]; if (clIndex >= ColorAxesGrids.Length) clIndex = 0; } } }
public void ApplyToChart(FastChart chart) { chart.Padding = Padding; chart.DrawMargin = DrawMargin; if (PenMargin != null) { chart.penMargin = PenMargin; } if (BrushArea != null) { chart.brushArea = BrushArea; } chart.UseGradient = UseGradient; chart.ClGradStart = ClGradStart; chart.ClGradEnd = ClGradEnd; chart.GradAngle = GradAngle; if (ChartFont != null) { chart.Font = ChartFont; } if (ColorAxes.Length > 0) { var clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.X)) { if (ax.LineColor.HasValue) { continue; } ax.LineColor = ColorAxes[clIndex++]; if (clIndex >= ColorAxes.Length) { clIndex = 0; } } clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.Y)) { if (ax.LineColor.HasValue) { continue; } ax.LineColor = ColorAxes[clIndex++]; if (clIndex >= ColorAxes.Length) { clIndex = 0; } } } if (ColorAxesGrids.Length > 0) { var clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.X)) { if (ax.ColorMainGrid.HasValue) { continue; } ax.ColorMainGrid = ColorAxesGrids[clIndex++]; if (clIndex >= ColorAxesGrids.Length) { clIndex = 0; } } clIndex = 0; foreach (var ax in chart.Axes.FindAll(a => a.Direction == FastAxisDirection.Y)) { if (ax.ColorMainGrid.HasValue) { continue; } ax.ColorMainGrid = ColorAxesGrids[clIndex++]; if (clIndex >= ColorAxesGrids.Length) { clIndex = 0; } } } }
/// <returns>размер, отъедаемый легендой от графика</returns> public Size DrawLegend(PaintEventArgs e, FastChart owner) { if (!ShowLegend || owner.series.Count == 0) { return(new Size(0, 0)); } const int legRecHeight = 40; var legendHeight = owner.series.Count * legRecHeight; var legendHeightFull = LegendInnerPadding * 2 + legendHeight; if (Width < (LengthMinWidth + 120 + LegendPadding * 2) || Height < (legendHeightFull + 100 + LegendPadding * 2)) { return(new Size(0, 0)); } var rect = LegendPlacement == ChartLegendPlacement.Вверху ? new Rectangle(Math.Max(Width / 5, LegendPadding), LegendPadding, Math.Min(Width * 4 / 5, LegendPadding), legendHeightFull) : new Rectangle(Width - lengthMinWidth - LegendPadding, LegendPadding, lengthMinWidth, legendHeightFull); // нарисовать тень if (DrawShadow) { rect.Offset(4, 4); e.Graphics.FillRectangle(legendShadowBrush, rect); rect.Offset(-4, -4); } // закрасить e.Graphics.FillRectangle(legendBrush, rect); // рамка if (DrawLegendMargin) { e.Graphics.DrawRectangle(penLegend, rect); } // текст var textY = rect.Top + LegendInnerPadding; var textX = rect.Left + LegendInnerPadding; using (var brushText = new SolidBrush(LegendMarginColor)) { foreach (var sr in owner.series) { var txtSz = e.Graphics.MeasureString(sr.Name, owner.Font); // точка using (var brushDot = new SolidBrush(sr.PenLine != null ? sr.PenLine.Color : Color.DarkGray)) { e.Graphics.FillRectangle(brushDot, textX, textY + legRecHeight / 2 - 4, 4, 4); } // текст e.Graphics.DrawString(sr.Name, owner.Font, brushText, textX + 7, textY + legRecHeight / 2 - txtSz.Height / 2); textY += legRecHeight; } } return(new Size(lengthMinWidth + LegendPadding * 2, legendHeightFull + LegendPadding * 2)); }
/// <summary> /// вернуть полный путь к файлу с картинкой доходности /// </summary> private string MakeProfitChart(string tempFolder, Size chartSize) { var chart = new FastChart.Chart.FastChart { ShowLegend = true, LegendPlacement = FastChart.Chart.FastChart.ChartLegendPlacement.Справа, BorderStyle = BorderStyle.None, DrawMargin = false }; var axisX = new FastAxis(FastAxisDirection.X, true) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, Step = new FastChart.Chart.Cortege2<double, TimeSpan>(0, new TimeSpan(356, 0, 0, 0)), LabelFormat = "yyyy" }; var maxProfit = (double) profitDic.Max(p => p.equity); var axisY = new FastAxis(FastAxisDirection.Y, false) { ColorMainGrid = Color.FromArgb(205, 205, 205), ColorSubGrid = Color.FromArgb(220, 220, 220), DrawMainGrid = true, DrawSubGrid = true, AutoScale100 = false, MinValue = new FastChart.Chart.Cortege2<double, DateTime>(0, default(DateTime)), MaxValue = new FastChart.Chart.Cortege2<double, DateTime>(maxProfit * 1.1, default(DateTime)) }; if (maxProfit > 1000) { var stepSize = maxProfit < 2000 ? 200 : maxProfit < 4000 ? 500 : 1000; axisY.Step = new FastChart.Chart.Cortege2<double, TimeSpan>(stepSize, default(TimeSpan)); } chart.Axes.Add(axisX); chart.Axes.Add(axisY); var seriesFund = new FastSeries("УК", FastSeriesType.Линия, axisX, axisY, false) {PenLine = new Pen(Color.FromArgb(80, 5, 5), 2f), AntiAlias = true }; seriesFund.points.AddRange(profitDic.Select(p => new FastSeriesPoint(p.time, p.equity)).ToList()); chart.series.Add(seriesFund); // серии бенчмарков var seriesBmA = new FastSeries(benchmarkA, FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(Color.FromArgb(5, 80, 5), 2f), AntiAlias = true }; var seriesBmB = new FastSeries(benchmarkB, FastSeriesType.Линия, axisX, axisY, false) { PenLine = new Pen(Color.FromArgb(5, 5, 80), 2f), AntiAlias = true }; seriesBmA.points.AddRange(MakeBenchmarkProfit1000Points(vamiBenchmarkA)); seriesBmB.points.AddRange(MakeBenchmarkProfit1000Points(vamiBenchmarkB)); chart.series.Add(seriesBmA); chart.series.Add(seriesBmB); chart.Width = chartSize.Width; chart.Height = chartSize.Height; var img = new Bitmap(chartSize.Width, chartSize.Height); chart.DrawToBitmap(img, new Rectangle(0, 0, chartSize.Width, chartSize.Height)); var path = string.Format("{0}\\chartProfit1000_{1}.png", tempFolder, DateTime.Now.Millisecond); img.Save(path, ImageFormat.Png); return path; }