Skip to content

Commit f6bb6ea

Browse files
committed
Added corrected calculation of lines for pie chart
1 parent 3b2818e commit f6bb6ea

5 files changed

Lines changed: 96 additions & 34 deletions

File tree

src/EPPlus.Export.ImageRenderer.Test/Chart/PieChartTests.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
namespace EPPlus.Export.ImageRenderer.Tests.Chart
99
{
10-
internal class PieChartTests : TestBase
10+
[TestClass]
11+
public class PieChartTests : TestBase
1112
{
1213
[TestMethod]
13-
public void GenerateSvgForColumnCharts1()
14+
public void GenerateSvgForPieChart()
1415
{
1516
ExcelPackage.License.SetNonCommercialOrganization("EPPlus Project");
1617
using (var p = OpenTemplatePackage("BasicPieChart.xlsx"))
@@ -22,7 +23,7 @@ public void GenerateSvgForColumnCharts1()
2223
foreach (ExcelChart c in ws.Drawings)
2324
{
2425
var svg = renderer.RenderDrawingToSvg(c);
25-
SaveTextFileToWorkbook($"svg\\ChartForSvg{ix++}.svg", svg);
26+
SaveTextFileToWorkbook($"svg\\PieChartForSvg{ix++}.svg", svg);
2627
}
2728
}
2829
}

src/EPPlus.Export.ImageRenderer/Svg/Chart/ChartTypeDrawers/ChartTypeDrawer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using EPPlus.Export.ImageRenderer.Utils;
1+
using EPPlus.Export.ImageRenderer.Svg.Chart.ChartTypeDrawers;
2+
using EPPlus.Export.ImageRenderer.Utils;
23
using EPPlusImageRenderer.RenderItems;
34
using EPPlusImageRenderer.Svg;
45
using OfficeOpenXml;
@@ -82,6 +83,9 @@ internal static List<ChartTypeDrawer> Create(SvgChart svgChart)
8283
case eChartType.BarStacked100:
8384
drawers.Add(new BarColumnChartTypeDrawer(svgChart, (ExcelBarChart)ct));
8485
break;
86+
case eChartType.Pie:
87+
drawers.Add(new PieChartTypeDrawer(svgChart, (ExcelPieChart)ct));
88+
break;
8589
default:
8690
throw new NotImplementedException($"No Svg support for Chart type {ct} is implemented.");
8791
}

src/EPPlus.Export.ImageRenderer/Svg/Chart/ChartTypeDrawers/PieChartTypeDrawer.cs

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
using EPPlus.Graphics;
1+
using EPPlus.Fonts.OpenType.Utils;
2+
using EPPlus.Graphics;
23
using EPPlusImageRenderer;
34
using EPPlusImageRenderer.RenderItems;
45
using EPPlusImageRenderer.Svg;
5-
using OfficeOpenXml.Drawing;
66
using OfficeOpenXml.Drawing.Chart;
7-
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
7+
using OfficeOpenXml.FormulaParsing.Excel.Functions.MathFunctions;
88
using OfficeOpenXml.Utils.TypeConversion;
99
using System;
1010
using System.Collections.Generic;
11-
using System.Linq;
12-
using System.Text;
11+
using System.Drawing;
1312

1413
namespace EPPlus.Export.ImageRenderer.Svg.Chart.ChartTypeDrawers
1514
{
@@ -32,13 +31,8 @@ public PieChartTypeDrawer(SvgChart chart, ExcelPieChart chartType) : base(chart,
3231

3332
foreach (ExcelPieChartSerie serie in chartType.Series)
3433
{
35-
List<object> valValue, catValue;
36-
37-
valValue = LoadSeriesValues(serie.Series, serie.NumberLiteralsY, serie.StringLiteralsY);
38-
catValue = LoadSeriesValues(serie.XSeries, serie.NumberLiteralsX, serie.StringLiteralsX);
39-
40-
catValues.Add(catValue);
41-
valValues.Add(valValue);
34+
valValues = LoadSeriesValues(serie.Series, serie.NumberLiteralsY, serie.StringLiteralsY);
35+
catValues = LoadSeriesValues(serie.XSeries, serie.NumberLiteralsX, serie.StringLiteralsX);
4236

4337
serCounter++;
4438
}
@@ -48,46 +42,106 @@ public PieChartTypeDrawer(SvgChart chart, ExcelPieChart chartType) : base(chart,
4842

4943
for(int i = 0; i< valValues.Count; i++)
5044
{
51-
valValuesDoubles.Add(ConvertUtil.GetValueDouble(valValues[i], false, true));
45+
var origValue = valValues[i];
46+
var dValue = ConvertUtil.GetValueDouble(origValue, false, true);
47+
valValuesDoubles.Add(dValue);
5248
valTotal += valValuesDoubles[i];
5349
}
5450

5551
var cx = _svgChart.Plotarea.Rectangle.Bounds.Width / 2;
5652
var cy = _svgChart.Plotarea.Rectangle.Bounds.Height / 2;
5753

58-
var radius = Math.Min(_svgChart.Plotarea.Rectangle.Bounds.Height, _svgChart.Plotarea.Rectangle.Bounds.Width);
54+
var radius = Math.Min(cx, cy);
5955

56+
groupItem.Bounds.Left = radius;
57+
groupItem.Bounds.Top = radius;
58+
59+
var prevAngle = -90d;
6060

6161
for (int i = 0; i < valValues.Count; i++)
6262
{
6363
valPercent.Add(valValuesDoubles[i] / valTotal);
64-
circleSectorAngle.Add(valPercent[i] / 360d);
65-
var xPoint = cx + (radius * Math.Cos(circleSectorAngle[i]));
66-
var yPoint = cy + (radius * Math.Sin(circleSectorAngle[i]));
64+
65+
var angle = valPercent[i] * 360d;
66+
67+
angle += prevAngle;
68+
69+
circleSectorAngle.Add(angle);
70+
71+
var angleRadians = angle * (Math.PI / 180.0d);
72+
73+
var xPoint = cx + (radius * Math.Cos(angleRadians));
74+
var yPoint = cy + (radius * Math.Sin(angleRadians));
6775
endCoordOffsetFromCenterOfCircle.Add(new Coordinate(xPoint, yPoint));
76+
77+
prevAngle = angle;
6878
}
6979

7080
var count = Math.Min(catValues.Count, valValues.Count);
71-
for (var i = 0; i < catValues.Count; i++)
81+
82+
for(int i = 0; i < chartType.Series.Count; i++)
7283
{
7384
var serie = (ExcelPieChartSerie)chartType.Series[i];
85+
for (var j = 0; j < catValues.Count; j++)
86+
{
87+
var total = ConvertUtil.GetValueDouble(catValues[j], false, true);
7488

75-
var total = ConvertUtil.GetValueDouble(catValues[i], false, true);
76-
77-
var dataPoints = new List<BoundingBox>();
78-
79-
//Add the slice.
80-
AddSlice(chartType, serie, catValues, valValues, dataPoints, count, i, radius);
81-
89+
var dataPoints = new List<BoundingBox>();
8290

91+
//Add the slice.
92+
AddSlice(chartType, serie, catValues, valValues, dataPoints, count, j, radius);
93+
}
8394
}
95+
8496
RenderItems.Add(new SvgEndGroupItem(ChartRenderer, null));
8597
}
8698

8799
private void AddSlice(ExcelPieChart chartType, ExcelPieChartSerie serie, List<object> catSeries, List<object> valSeries, List<BoundingBox> dataPoints, int seriesCount, int position, double radius)
88100
{
89-
var slice = new SvgRenderEllipseItem(ChartRenderer, _svgChart.Plotarea.Rectangle.Bounds);
101+
var slice = new SvgRenderPathItem(ChartRenderer, _svgChart.Plotarea.Rectangle.Bounds);
102+
103+
var cx = _svgChart.Plotarea.Rectangle.Bounds.Width / 2;
104+
var cy = _svgChart.Plotarea.Rectangle.Bounds.Height / 2;
105+
106+
var moveCenter = new PathCommands(PathCommandType.Move, slice, cx/_svgChart.Bounds.Width, cy/_svgChart.Bounds.Height);
107+
Coordinate startPoint;
108+
if(position != 0)
109+
{
110+
startPoint = new Coordinate(endCoordOffsetFromCenterOfCircle[position - 1].X, endCoordOffsetFromCenterOfCircle[position - 1].Y);
111+
}
112+
else
113+
{
114+
startPoint = new Coordinate(cx, 0);
115+
}
116+
117+
var lineToStart = new PathCommands(PathCommandType.Line, slice, startPoint.X / _svgChart.Bounds.Width, startPoint.Y / _svgChart.Bounds.Height);
118+
119+
var lineToEndPoint = new PathCommands(PathCommandType.Line, slice, endCoordOffsetFromCenterOfCircle[position].X / _svgChart.Bounds.Width, endCoordOffsetFromCenterOfCircle[position].Y / _svgChart.Bounds.Height);
90120

121+
//var arcCommand = new PathCommands(PathCommandType.Arc, slice, new double[] { startPoint.X / _svgChart.Bounds.Width, startPoint.Y / _svgChart.Bounds.Height, 0, 0, 1, endCoordOffsetFromCenterOfCircle[position].X / _svgChart.Bounds.Width, endCoordOffsetFromCenterOfCircle[position].Y / _svgChart.Bounds.Height });
122+
123+
slice.Commands.Add(moveCenter);
124+
slice.Commands.Add(lineToStart);
125+
126+
slice.Commands.Add(moveCenter);
127+
slice.Commands.Add(lineToEndPoint);
128+
129+
if(position == 0)
130+
{
131+
serie.Fill.Color = Color.Red;
132+
serie.Border.Fill.Color = Color.DarkOrange;
133+
}
134+
else if(position == 1)
135+
{
136+
serie.Fill.Color = Color.Green;
137+
serie.Border.Fill.Color = Color.DarkGreen;
138+
}
139+
else if(position == 2)
140+
{
141+
serie.Fill.Color = Color.Blue;
142+
serie.Border.Fill.Color = Color.DarkBlue;
143+
}
144+
//slice.Commands.Add(arcCommand);
91145

92146
slice.SetDrawingPropertiesFill(serie.Fill, chartType.StyleManager.Style.SeriesAxis.FillReference.Color);
93147
slice.SetDrawingPropertiesBorder(serie.Border, chartType.StyleManager.Style.SeriesAxis.BorderReference.Color, true);

src/EPPlus.Export.ImageRenderer/Svg/Chart/SvgChart.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ public SvgChart(ExcelChart chart) : base(chart)
5454
Legend = null;
5555
}
5656

57-
HorizontalAxis = GetAxis(false);
58-
VerticalAxis = GetAxis(true);
57+
if(Chart.Axis.Length != 0)
58+
{
59+
HorizontalAxis = GetAxis(false);
60+
VerticalAxis = GetAxis(true);
61+
}
5962

6063
if(chart.Axis.Length > 2)
6164
{

src/EPPlus.Export.ImageRenderer/Svg/Chart/SvgChartLegend.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,11 @@ internal override void AppendRenderItems(List<RenderItem> renderItems)
478478
renderItems.Add(Rectangle);
479479
foreach(var s in SeriesIcon)
480480
{
481-
renderItems.Add(s.SeriesIcon);
481+
if(s.SeriesIcon != null) renderItems.Add(s.SeriesIcon);
482482
if(s.MarkerBackground != null) renderItems.Add(s.MarkerBackground);
483483
if (s.MarkerIcon != null) renderItems.Add(s.MarkerIcon);
484484
//renderItems.Add(s.Textbox);
485-
s.Textbox.AppendRenderItems(renderItems);
485+
if(s.Textbox != null) s.Textbox.AppendRenderItems(renderItems);
486486
}
487487
renderItems.Add(new SvgEndGroupItem(ChartRenderer, null));
488488
}

0 commit comments

Comments
 (0)