/// <summary> /// Calculates the space used by the data labels. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri._dataLabelRendererInfo == null) { continue; } XGraphics gfx = _rendererParms.Graphics; sri._dataLabelRendererInfo.Entries = new DataLabelEntryRendererInfo[sri._pointRendererInfos.Length]; int index = 0; foreach (ColumnRendererInfo column in sri._pointRendererInfos) { DataLabelEntryRendererInfo dleri = new DataLabelEntryRendererInfo(); if (sri._dataLabelRendererInfo.Type != DataLabelType.None) { if (sri._dataLabelRendererInfo.Type == DataLabelType.Value) { dleri.Text = column.Point._value.ToString(sri._dataLabelRendererInfo.Format); } else if (sri._dataLabelRendererInfo.Type == DataLabelType.Percent) { throw new InvalidOperationException(PSCSR.PercentNotSupportedByColumnDataLabel); } if (dleri.Text.Length > 0) { dleri.Size = gfx.MeasureString(dleri.Text, sri._dataLabelRendererInfo.Font); } } sri._dataLabelRendererInfo.Entries[index++] = dleri; } } CalcPositions(); }
/// <summary> /// Determines the sum of the smallest and the largest stacked column /// from all series of the chart. /// </summary> protected override void CalcYAxis(out double yMin, out double yMax) { yMin = Double.MaxValue; yMax = Double.MinValue; ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; int maxPoints = 0; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { maxPoints = Math.Max(maxPoints, sri._series._seriesElements.Count); } for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx) { double valueSumPos = 0, valueSumNeg = 0; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri._pointRendererInfos.Length <= pointIdx) { break; } ColumnRendererInfo column = (ColumnRendererInfo)sri._pointRendererInfos[pointIdx]; if (column.Point != null && !Double.IsNaN(column.Point._value)) { if (column.Point._value < 0) { valueSumNeg += column.Point._value; } else { valueSumPos += column.Point._value; } } } yMin = Math.Min(valueSumNeg, yMin); yMax = Math.Max(valueSumPos, yMax); } }
/// <summary> /// Draws the content of the area plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } XGraphics gfx = _rendererParms.Graphics; XGraphicsState state = gfx.Save(); //gfx.SetClip(plotAreaRect, XCombineMode.Intersect); gfx.IntersectClip(plotAreaRect); XMatrix matrix = cri.plotAreaRendererInfo._matrix; double xMajorTick = cri.xAxisRendererInfo.MajorTick; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { int count = sri._series.Elements.Count; XPoint[] points = new XPoint[count + 2]; points[0] = new XPoint(xMajorTick / 2, 0); for (int idx = 0; idx < count; idx++) { double pointValue = sri._series.Elements[idx].Value; if (System.Double.IsNaN(pointValue)) { pointValue = 0; } points[idx + 1] = new XPoint(idx + xMajorTick / 2, pointValue); } points[count + 1] = new XPoint(count - 1 + xMajorTick / 2, 0); matrix.TransformPoints(points); gfx.DrawPolygon(sri.LineFormat, sri.FillFormat, points, XFillMode.Winding); } //gfx.ResetClip(); gfx.Restore(state); }
/// <summary> /// Returns a initialized rendererInfo based on the Y axis. /// </summary> internal override RendererInfo Init() { Chart chart = (Chart)_rendererParms.DrawingItem; XGraphics gfx = _rendererParms.Graphics; AxisRendererInfo yari = new AxisRendererInfo { _axis = chart._yAxis }; InitScale(yari); if (yari._axis != null) { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; InitTickLabels(yari, cri.DefaultFont); InitAxisTitle(yari, cri.DefaultFont); InitAxisLineFormat(yari); InitGridlines(yari); } return(yari); }
/// <summary> /// Draws the column chart. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms); lr.Draw(); WallRenderer wr = new WallRenderer(_rendererParms); wr.Draw(); GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(_rendererParms); glr.Draw(); PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms); pabr.Draw(); PlotAreaRenderer renderer = GetPlotAreaRenderer(); renderer.Draw(); DataLabelRenderer dlr = new ColumnDataLabelRenderer(_rendererParms); dlr.Draw(); if (cri.xAxisRendererInfo._axis != null) { AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms); xar.Draw(); } if (cri.yAxisRendererInfo._axis != null) { AxisRenderer yar = GetYAxisRenderer(); yar.Draw(); } }
/// <summary> /// Calculates the space used by the legend and returns the remaining space available for the /// other parts of the chart. /// </summary> protected XRect LayoutLegend() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; XRect remainingRect = _rendererParms.Box; if (cri.legendRendererInfo != null) { switch (cri.legendRendererInfo._legend.Docking) { case DockingType.Left: cri.legendRendererInfo.X = remainingRect.Left; cri.legendRendererInfo.Y = remainingRect.Height / 2 - cri.legendRendererInfo.Height / 2; double width = cri.legendRendererInfo.Width + LegendSpacing; remainingRect.X += width; remainingRect.Width -= width; break; case DockingType.Right: cri.legendRendererInfo.X = remainingRect.Right - cri.legendRendererInfo.Width; cri.legendRendererInfo.Y = remainingRect.Height / 2 - cri.legendRendererInfo.Height / 2; remainingRect.Width -= cri.legendRendererInfo.Width + LegendSpacing; break; case DockingType.Top: cri.legendRendererInfo.X = remainingRect.Width / 2 - cri.legendRendererInfo.Width / 2; cri.legendRendererInfo.Y = remainingRect.Top; double height = cri.legendRendererInfo.Height + LegendSpacing; remainingRect.Y += height; remainingRect.Height -= height; break; case DockingType.Bottom: cri.legendRendererInfo.X = remainingRect.Width / 2 - cri.legendRendererInfo.Width / 2; cri.legendRendererInfo.Y = remainingRect.Bottom - cri.legendRendererInfo.Height; remainingRect.Height -= cri.legendRendererInfo.Height + LegendSpacing; break; } } return(remainingRect); }
/// <summary> /// Layouts and calculates the space used by the column chart. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; LegendRenderer lr = GetLegendRenderer(); lr.Format(); // axes AxisRenderer xar = new VerticalXAxisRenderer(_rendererParms); xar.Format(); AxisRenderer yar = GetYAxisRenderer(); yar.Format(); // Calculate rects and positions. XRect chartRect = LayoutLegend(); cri.xAxisRendererInfo.X = chartRect.Left; cri.xAxisRendererInfo.Y = chartRect.Top; cri.xAxisRendererInfo.Height = chartRect.Height - cri.yAxisRendererInfo.Height; cri.yAxisRendererInfo.X = chartRect.Left + cri.xAxisRendererInfo.Width; cri.yAxisRendererInfo.Y = chartRect.Bottom - cri.yAxisRendererInfo.Height; cri.yAxisRendererInfo.Width = chartRect.Width - cri.xAxisRendererInfo.Width; cri.plotAreaRendererInfo.X = cri.yAxisRendererInfo.X; cri.plotAreaRendererInfo.Y = cri.xAxisRendererInfo.Y; cri.plotAreaRendererInfo.Width = cri.yAxisRendererInfo.InnerRect.Width; cri.plotAreaRendererInfo.Height = cri.xAxisRendererInfo.Height; // Calculated remaining plot area, now it's safe to format. PlotAreaRenderer renderer = GetPlotAreaRenderer(); renderer.Format(); DataLabelRenderer dlr = new BarDataLabelRenderer(_rendererParms); dlr.Format(); }
/// <summary> /// Draws the line chart. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; LegendRenderer lr = new ColumnLikeLegendRenderer(_rendererParms); lr.Draw(); // Draw wall. WallRenderer wr = new WallRenderer(_rendererParms); wr.Draw(); // Draw gridlines. GridlinesRenderer glr = new ColumnLikeGridlinesRenderer(_rendererParms); glr.Draw(); PlotAreaBorderRenderer pabr = new PlotAreaBorderRenderer(_rendererParms); pabr.Draw(); // Draw line chart's plot area. LinePlotAreaRenderer lpar = new LinePlotAreaRenderer(_rendererParms); lpar.Draw(); // Draw x- and y-axis. if (cri.xAxisRendererInfo._axis != null) { AxisRenderer xar = new HorizontalXAxisRenderer(_rendererParms); xar.Draw(); } if (cri.yAxisRendererInfo._axis != null) { AxisRenderer yar = new VerticalYAxisRenderer(_rendererParms); yar.Draw(); } }
/// <summary> /// Draws the content of the pie plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } if (cri.seriesRendererInfos.Length == 0) { return; } XGraphics gfx = _rendererParms.Graphics; XGraphicsState state = gfx.Save(); // Draw sectors. SeriesRendererInfo sri = cri.seriesRendererInfos[0]; foreach (SectorRendererInfo sector in sri._pointRendererInfos) { if (!System.Double.IsNaN(sector.StartAngle) && !System.Double.IsNaN(sector.SweepAngle)) { gfx.DrawPie(sector.FillFormat, sector.Rect, sector.StartAngle, sector.SweepAngle); } } // Draw border of the sectors. foreach (SectorRendererInfo sector in sri._pointRendererInfos) { if (!System.Double.IsNaN(sector.StartAngle) && !System.Double.IsNaN(sector.SweepAngle)) { gfx.DrawPie(sector.LineFormat, sector.Rect, sector.StartAngle, sector.SweepAngle); } } gfx.Restore(state); }
/// <summary> /// Returns an initialized rendererInfo based on the X axis. /// </summary> internal override RendererInfo Init() { Chart chart = (Chart)_rendererParms.DrawingItem; AxisRendererInfo xari = new AxisRendererInfo { _axis = chart._xAxis }; if (xari._axis != null) { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; CalculateXAxisValues(xari); InitTickLabels(xari, cri.DefaultFont); InitXValues(xari); InitAxisTitle(xari, cri.DefaultFont); InitAxisLineFormat(xari); InitGridlines(xari); } return(xari); }
/// <summary> /// Initializes all necessary data to draw a series for a pie chart. /// </summary> protected void InitSeries(ChartRendererInfo rendererInfo) { SeriesCollection seriesColl = rendererInfo._chart.SeriesCollection; rendererInfo.seriesRendererInfos = new SeriesRendererInfo[seriesColl.Count]; for (int idx = 0; idx < seriesColl.Count; ++idx) { SeriesRendererInfo sri = new SeriesRendererInfo(); rendererInfo.seriesRendererInfos[idx] = sri; sri._series = seriesColl[idx]; sri.LineFormat = Converter.ToXPen(sri._series._lineFormat, XColors.Black, ChartRenderer.DefaultSeriesLineWidth); sri.FillFormat = Converter.ToXBrush(sri._series._fillFormat, ColumnColors.Item(idx)); sri._pointRendererInfos = new SectorRendererInfo[sri._series._seriesElements.Count]; for (int pointIdx = 0; pointIdx < sri._pointRendererInfos.Length; ++pointIdx) { PointRendererInfo pri = new SectorRendererInfo(); Point point = sri._series._seriesElements[pointIdx]; pri.Point = point; if (point != null) { pri.LineFormat = sri.LineFormat; if (point._lineFormat != null && !point._lineFormat._color.IsEmpty) { pri.LineFormat = new XPen(point._lineFormat._color); } pri.FillFormat = point._fillFormat != null && !point._fillFormat._color.IsEmpty ? new XSolidBrush(point._fillFormat._color) : new XSolidBrush(PieColors.Item(pointIdx)); pri.LineFormat.LineJoin = XLineJoin.Round; } sri._pointRendererInfos[pointIdx] = pri; } } }
/// <summary> /// Layouts and calculates the space used by the legend. /// </summary> internal override void Format() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; LegendRendererInfo lri = cri.legendRendererInfo; if (lri == null) { return; } RendererParameters parms = new RendererParameters { Graphics = _rendererParms.Graphics }; bool verticalLegend = lri._legend._docking == DockingType.Left || lri._legend._docking == DockingType.Right; XSize maxMarkerArea = new XSize(); LegendEntryRenderer ler = new LegendEntryRenderer(parms); foreach (LegendEntryRendererInfo leri in lri.Entries) { parms.RendererInfo = leri; ler.Format(); maxMarkerArea.Width = Math.Max(leri.MarkerArea.Width, maxMarkerArea.Width); maxMarkerArea.Height = Math.Max(leri.MarkerArea.Height, maxMarkerArea.Height); if (verticalLegend) { lri.Width = Math.Max(lri.Width, leri.Width); lri.Height += leri.Height; } else { lri.Width += leri.Width; lri.Height = Math.Max(lri.Height, leri.Height); } } // Add padding to left, right, top and bottom int paddingFactor = 1; if (lri.BorderPen != null) { paddingFactor = 2; } lri.Width += (LegendRenderer.LeftPadding + LegendRenderer.RightPadding) * paddingFactor; lri.Height += (LegendRenderer.TopPadding + LegendRenderer.BottomPadding) * paddingFactor; if (verticalLegend) { lri.Height += LegendRenderer.EntrySpacing * (lri.Entries.Length - 1); } else { lri.Width += LegendRenderer.EntrySpacing * (lri.Entries.Length - 1); } foreach (LegendEntryRendererInfo leri in lri.Entries) { leri.MarkerArea = maxMarkerArea; } }
/// <summary> /// Draws the legend. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; LegendRendererInfo lri = cri.legendRendererInfo; if (lri == null) { return; } XGraphics gfx = _rendererParms.Graphics; RendererParameters parms = new RendererParameters { Graphics = gfx }; LegendEntryRenderer ler = new LegendEntryRenderer(parms); bool verticalLegend = lri._legend._docking == DockingType.Left || lri._legend._docking == DockingType.Right; int paddingFactor = 1; if (lri.BorderPen != null) { paddingFactor = 2; } XRect legendRect = lri.Rect; legendRect.X += LeftPadding * paddingFactor; if (verticalLegend) { legendRect.Y = legendRect.Bottom - BottomPadding * paddingFactor; } else { legendRect.Y += TopPadding * paddingFactor; } foreach (LegendEntryRendererInfo leri in cri.legendRendererInfo.Entries) { if (verticalLegend) { legendRect.Y -= leri.Height; } XRect entryRect = legendRect; entryRect.Width = leri.Width; entryRect.Height = leri.Height; leri.Rect = entryRect; parms.RendererInfo = leri; ler.Draw(); if (verticalLegend) { legendRect.Y -= EntrySpacing; } else { legendRect.X += entryRect.Width + EntrySpacing; } } // Draw border around legend if (lri.BorderPen != null) { XRect borderRect = lri.Rect; borderRect.X += LeftPadding; borderRect.Y += TopPadding; borderRect.Width -= LeftPadding + RightPadding; borderRect.Height -= TopPadding + BottomPadding; gfx.DrawRectangle(lri.BorderPen, borderRect); } }
/// <summary> /// Calculates the position, width and height of each column of all series. /// </summary> protected override void CalcColumns() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } double xMin = cri.xAxisRendererInfo.MinimumScale; double xMajorTick = cri.xAxisRendererInfo.MajorTick; int maxPoints = 0; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { maxPoints = Math.Max(maxPoints, sri._series._seriesElements.Count); } double x = xMin + xMajorTick / 2; // Space used by one column. double columnWidth = xMajorTick * 0.75 / 2; XPoint[] points = new XPoint[2]; for (int pointIdx = 0; pointIdx < maxPoints; ++pointIdx) { // Set x to first clustered column for each series. double yMin = 0, yMax = 0, y0 = 0, y1 = 0; double x0 = x - columnWidth; double x1 = x + columnWidth; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { if (sri._pointRendererInfos.Length <= pointIdx) { break; } ColumnRendererInfo column = (ColumnRendererInfo)sri._pointRendererInfos[pointIdx]; if (column.Point != null && !Double.IsNaN(column.Point._value)) { double y = column.Point._value; if (y < 0) { y0 = yMin + y; y1 = yMin; yMin += y; } else { y0 = yMax; y1 = yMax + y; yMax += y; } points[0].X = x0; // upper left points[0].Y = y1; points[1].X = x1; // lower right points[1].Y = y0; cri.plotAreaRendererInfo._matrix.TransformPoints(points); column.Rect = new XRect(points[0].X, points[0].Y, points[1].X - points[0].X, points[1].Y - points[0].Y); } } x++; // Next stacked column. } }
/// <summary> /// Calculates the data label positions specific for pie charts. /// </summary> internal override void CalcPositions() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; XGraphics gfx = _rendererParms.Graphics; if (cri.seriesRendererInfos.Length > 0) { SeriesRendererInfo sri = cri.seriesRendererInfos[0]; if (sri != null && sri._dataLabelRendererInfo != null) { int sectorIndex = 0; foreach (SectorRendererInfo sector in sri._pointRendererInfos) { // Determine output rectangle double midAngle = sector.StartAngle + sector.SweepAngle / 2; double radMidAngle = midAngle / 180 * Math.PI; XPoint origin = new XPoint(sector.Rect.X + sector.Rect.Width / 2, sector.Rect.Y + sector.Rect.Height / 2); double radius = sector.Rect.Width / 2; double halfradius = radius / 2; DataLabelEntryRendererInfo dleri = sri._dataLabelRendererInfo.Entries[sectorIndex++]; switch (sri._dataLabelRendererInfo.Position) { case DataLabelPosition.OutsideEnd: // Outer border of the circle. dleri.X = origin.X + radius * Math.Cos(radMidAngle); dleri.Y = origin.Y + radius * Math.Sin(radMidAngle); if (dleri.X < origin.X) { dleri.X -= dleri.Width; } if (dleri.Y < origin.Y) { dleri.Y -= dleri.Height; } break; case DataLabelPosition.InsideEnd: // Inner border of the circle. dleri.X = origin.X + radius * Math.Cos(radMidAngle); dleri.Y = origin.Y + radius * Math.Sin(radMidAngle); if (dleri.X > origin.X) { dleri.X -= dleri.Width; } if (dleri.Y > origin.Y) { dleri.Y -= dleri.Height; } break; case DataLabelPosition.Center: // Centered dleri.X = origin.X + halfradius * Math.Cos(radMidAngle); dleri.Y = origin.Y + halfradius * Math.Sin(radMidAngle); dleri.X -= dleri.Width / 2; dleri.Y -= dleri.Height / 2; break; case DataLabelPosition.InsideBase: // Aligned at the base/center of the circle dleri.X = origin.X; dleri.Y = origin.Y; if (dleri.X < origin.X) { dleri.X -= dleri.Width; } if (dleri.Y < origin.Y) { dleri.Y -= dleri.Height; } break; } } } } }
/// <summary> /// Draws the gridlines into the plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; XRect plotAreaRect = cri.plotAreaRendererInfo.Rect; if (plotAreaRect.IsEmpty) { return; } AxisRendererInfo xari = cri.xAxisRendererInfo; AxisRendererInfo yari = cri.yAxisRendererInfo; double xMin = xari.MinimumScale; double xMax = xari.MaximumScale; double yMin = yari.MinimumScale; double yMax = yari.MaximumScale; double xMajorTick = xari.MajorTick; double yMajorTick = yari.MajorTick; double xMinorTick = xari.MinorTick; double yMinorTick = yari.MinorTick; double xMaxExtension = xari.MajorTick; XMatrix matrix = cri.plotAreaRendererInfo._matrix; LineFormatRenderer lineFormatRenderer; XGraphics gfx = _rendererParms.Graphics; XPoint[] points = new XPoint[2]; if (xari.MinorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, xari.MinorGridlinesLineFormat); for (double x = xMin + xMinorTick; x < xMax; x += xMinorTick) { points[0].Y = x; points[0].X = yMin; points[1].Y = x; points[1].X = yMax; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } if (xari.MajorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, xari.MajorGridlinesLineFormat); for (double x = xMin; x <= xMax; x += xMajorTick) { points[0].Y = x; points[0].X = yMin; points[1].Y = x; points[1].X = yMax; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } if (yari.MinorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, yari.MinorGridlinesLineFormat); for (double y = yMin + yMinorTick; y < yMax; y += yMinorTick) { points[0].Y = xMin; points[0].X = y; points[1].Y = xMax; points[1].X = y; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } if (yari.MajorGridlinesLineFormat != null) { lineFormatRenderer = new LineFormatRenderer(gfx, yari.MajorGridlinesLineFormat); for (double y = yMin; y <= yMax; y += yMajorTick) { points[0].Y = xMin; points[0].X = y; points[1].Y = xMax; points[1].X = y; matrix.TransformPoints(points); lineFormatRenderer.DrawLine(points[0], points[1]); } } }
/// <summary> /// Calculate angles for each sector. /// </summary> protected override void CalcSectors() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } SeriesRendererInfo sri = cri.seriesRendererInfos[0]; double sumValues = sri.SumOfPoints; if (sumValues == 0) { return; } double textMeasure = 0; if (sri._dataLabelRendererInfo != null && sri._dataLabelRendererInfo.Position == DataLabelPosition.OutsideEnd) { foreach (DataLabelEntryRendererInfo dleri in sri._dataLabelRendererInfo.Entries) { textMeasure = Math.Max(textMeasure, dleri.Width); textMeasure = Math.Max(textMeasure, dleri.Height); } } XRect pieRect = cri.plotAreaRendererInfo.Rect; if (textMeasure != 0) { pieRect.X += textMeasure; pieRect.Y += textMeasure; pieRect.Width -= 2 * textMeasure; pieRect.Height -= 2 * textMeasure; } XPoint origin = new XPoint(pieRect.X + pieRect.Width / 2, pieRect.Y + pieRect.Height / 2); XRect innerRect = new XRect(); XPoint p1 = new XPoint(); double midAngle = 0, sectorStartAngle = 0, sectorSweepAngle = 0, deltaAngle = 2, startAngle = 270, sweepAngle = 0, rInnerCircle = pieRect.Width / 15, rOuterCircle = pieRect.Width / 2; foreach (SectorRendererInfo sector in sri._pointRendererInfos) { if (!Double.IsNaN(sector.Point._value) && sector.Point._value != 0) { sweepAngle = 360 / (sumValues / Math.Abs(sector.Point._value)); midAngle = startAngle + sweepAngle / 2; sectorStartAngle = Math.Max(0, startAngle + deltaAngle); sectorSweepAngle = Math.Max(sweepAngle, sweepAngle - deltaAngle); p1.X = origin.X + rInnerCircle * Math.Cos(midAngle / 180 * Math.PI); p1.Y = origin.Y + rInnerCircle * Math.Sin(midAngle / 180 * Math.PI); innerRect.X = p1.X - rOuterCircle + rInnerCircle; innerRect.Y = p1.Y - rOuterCircle + rInnerCircle; innerRect.Width = (rOuterCircle - rInnerCircle) * 2; innerRect.Height = innerRect.Width; sector.Rect = innerRect; sector.StartAngle = sectorStartAngle; sector.SweepAngle = sectorSweepAngle; startAngle += sweepAngle; } else { sector.StartAngle = Double.NaN; sector.SweepAngle = Double.NaN; } } }
/// <summary> /// Calculates the position, width and height of each column of all series. /// </summary> protected override void CalcColumns() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; if (cri.seriesRendererInfos.Length == 0) { return; } double xMin = cri.xAxisRendererInfo.MinimumScale; double yMin = cri.yAxisRendererInfo.MinimumScale; double yMax = cri.yAxisRendererInfo.MaximumScale; int pointCount = 0; foreach (SeriesRendererInfo sr in cri.seriesRendererInfos) { pointCount += sr._series._seriesElements.Count; } // Space shared by one clustered column. double groupWidth = cri.xAxisRendererInfo.MajorTick; // Space used by one column. double columnWidth = groupWidth * 3 / 4 / cri.seriesRendererInfos.Length; int seriesIdx = 0; XPoint[] points = new XPoint[2]; foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { // Set x to first clustered column for each series. double x = xMin + groupWidth / 2; // Offset for columns of a particular series from the start of a clustered cloumn. double dx = columnWidth * seriesIdx - columnWidth / 2 * cri.seriesRendererInfos.Length; foreach (ColumnRendererInfo column in sri._pointRendererInfos) { if (column.Point != null) { double x0 = x + dx; double x1 = x + dx + columnWidth; double y0 = yMin; double y1 = column.Point.Value; // Draw from zero base line, if it exists. if (y0 < 0 && yMax >= 0) { y0 = 0; } // y0 should always be lower than y1, i. e. draw column from bottom to top. if (y1 < 0 && y1 < y0) { double y = y0; y0 = y1; y1 = y; } points[0].X = x0; // upper left points[0].Y = y1; points[1].X = x1; // lower right points[1].Y = y0; cri.plotAreaRendererInfo._matrix.TransformPoints(points); column.Rect = new XRect(points[0].X, points[0].Y, points[1].X - points[0].X, points[1].Y - points[0].Y); } x++; // Next clustered column. } seriesIdx++; } }
/// <summary> /// Draws the content of the column plot area. /// </summary> internal override void Draw() { ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; XRect plotAreaBox = cri.plotAreaRendererInfo.Rect; if (plotAreaBox.IsEmpty) { return; } XGraphics gfx = _rendererParms.Graphics; double xMin = cri.xAxisRendererInfo.MinimumScale; double xMax = cri.xAxisRendererInfo.MaximumScale; double yMin = cri.yAxisRendererInfo.MinimumScale; double yMax = cri.yAxisRendererInfo.MaximumScale; LineFormatRenderer lineFormatRenderer; // Under some circumstances it is possible that no zero base line will be drawn, // e. g. because of unfavourable minimum/maximum scale and/or major tick, so force to draw // a zero base line if necessary. if (cri.yAxisRendererInfo.MajorGridlinesLineFormat != null || cri.yAxisRendererInfo.MinorGridlinesLineFormat != null) { if (yMin < 0 && yMax > 0) { XPoint[] points = new XPoint[2]; points[0].X = xMin; points[0].Y = 0; points[1].X = xMax; points[1].Y = 0; cri.plotAreaRendererInfo._matrix.TransformPoints(points); lineFormatRenderer = cri.yAxisRendererInfo.MinorGridlinesLineFormat != null ? new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MinorGridlinesLineFormat) : new LineFormatRenderer(gfx, cri.yAxisRendererInfo.MajorGridlinesLineFormat); lineFormatRenderer.DrawLine(points[0], points[1]); } } // Draw columns XGraphicsState state = gfx.Save(); foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { foreach (ColumnRendererInfo column in sri._pointRendererInfos) { // Do not draw column if value is outside yMin/yMax range. Clipping does not make sense. if (IsDataInside(yMin, yMax, column.Point._value)) { gfx.DrawRectangle(column.FillFormat, column.Rect); } } } // Draw borders around column. // A border can overlap neighbor columns, so it is important to draw borders at the end. foreach (SeriesRendererInfo sri in cri.seriesRendererInfos) { foreach (ColumnRendererInfo column in sri._pointRendererInfos) { // Do not draw column if value is outside yMin/yMax range. Clipping does not make sense. if (IsDataInside(yMin, yMax, column.Point._value) && column.LineFormat.Width > 0) { lineFormatRenderer = new LineFormatRenderer(gfx, column.LineFormat); lineFormatRenderer.DrawRectangle(column.Rect); } } } gfx.Restore(state); }
/// <summary> /// Draws the horizontal X axis. /// </summary> internal override void Draw() { XGraphics gfx = _rendererParms.Graphics; ChartRendererInfo cri = (ChartRendererInfo)_rendererParms.RendererInfo; AxisRendererInfo xari = cri.xAxisRendererInfo; double xMin = xari.MinimumScale; double xMax = xari.MaximumScale; double xMajorTick = xari.MajorTick; double xMinorTick = xari.MinorTick; double xMaxExtension = xari.MajorTick; // Draw tick labels. Each tick label will be aligned centered. int countTickLabels = (int)xMax; double tickLabelStep = xari.Width; if (countTickLabels != 0) { tickLabelStep = xari.Width / countTickLabels; } //XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + /*xari.TickLabelsHeight +*/ xari.MajorTickMarkWidth); XPoint startPos = new XPoint(xari.X + tickLabelStep / 2, xari.Y + xari.TickLabelsHeight); if (xari.MajorTickMark != TickMarkType.None) { startPos.Y += xari.MajorTickMarkWidth; } foreach (XSeries xs in xari.XValues) { for (int idx = 0; idx < countTickLabels && idx < xs.Count; ++idx) { XValue xv = xs[idx]; if (xv != null) { string tickLabel = xv._value; XSize size = gfx.MeasureString(tickLabel, xari.TickLabelsFont); gfx.DrawString(tickLabel, xari.TickLabelsFont, xari.TickLabelsBrush, startPos.X - size.Width / 2, startPos.Y); } startPos.X += tickLabelStep; } } // Draw axis. // First draw tick marks, second draw axis. double majorTickMarkStart = 0, majorTickMarkEnd = 0, minorTickMarkStart = 0, minorTickMarkEnd = 0; GetTickMarkPos(xari, ref majorTickMarkStart, ref majorTickMarkEnd, ref minorTickMarkStart, ref minorTickMarkEnd); LineFormatRenderer lineFormatRenderer = new LineFormatRenderer(gfx, xari.LineFormat); XPoint[] points = new XPoint[2]; // Minor ticks. if (xari.MinorTickMark != TickMarkType.None) { int countMinorTickMarks = (int)(xMax / xMinorTick); double minorTickMarkStep = xari.Width / countMinorTickMarks; startPos.X = xari.X; for (int x = 0; x <= countMinorTickMarks; x++) { points[0].X = startPos.X + minorTickMarkStep * x; points[0].Y = minorTickMarkStart; points[1].X = points[0].X; points[1].Y = minorTickMarkEnd; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Major ticks. if (xari.MajorTickMark != TickMarkType.None) { int countMajorTickMarks = (int)(xMax / xMajorTick); double majorTickMarkStep = xari.Width; if (countMajorTickMarks != 0) { majorTickMarkStep = xari.Width / countMajorTickMarks; } startPos.X = xari.X; for (int x = 0; x <= countMajorTickMarks; x++) { points[0].X = startPos.X + majorTickMarkStep * x; points[0].Y = majorTickMarkStart; points[1].X = points[0].X; points[1].Y = majorTickMarkEnd; lineFormatRenderer.DrawLine(points[0], points[1]); } } // Axis. if (xari.LineFormat != null) { points[0].X = xari.X; points[0].Y = xari.Y; points[1].X = xari.X + xari.Width; points[1].Y = xari.Y; if (xari.MajorTickMark != TickMarkType.None) { points[0].X -= xari.LineFormat.Width / 2; points[1].X += xari.LineFormat.Width / 2; } lineFormatRenderer.DrawLine(points[0], points[1]); } // Draw axis title. AxisTitleRendererInfo atri = xari._axisTitleRendererInfo; if (atri != null && atri.AxisTitleText != null && atri.AxisTitleText.Length > 0) { XRect rect = new XRect(xari.Rect.Right / 2 - atri.AxisTitleSize.Width / 2, xari.Rect.Bottom, atri.AxisTitleSize.Width, 0); gfx.DrawString(atri.AxisTitleText, atri.AxisTitleFont, atri.AxisTitleBrush, rect); } }