• C#在Pdf画统计图表之【雷达图】(以五边形为例)


    前言

    工具:PdfSharpCore或Pdfsharp
    知识 :基本的三角函数
    思路 : 画坐标,确定点-------->画多个半径渐变的正多边形------->根据数据确定雷达图的数值位置

    StepOne:画一个正五边形

    先画一个辅助坐标轴,
    再通过三角函数确认其各个点的坐标,这里画一张图展示
    在这里插入图片描述
    因为pdfsharp默认的原点为左上角,正值为第四象限,
    所以为了更好的确定各点的坐标,
    则需要移动原点的位置,旋转坐标轴,以求设置为熟悉的常用坐标
    好在pdfsharpcore提供了现成的方法,调整起来也比较简单
    代码:

    const double PAI = Math.PI;
            static void Main(string[] args)
            {
                PdfDocument doc = new PdfDocument();
    
                PdfPage page = new PdfPage(doc);
    
                XGraphics graphics = XGraphics.FromPdfPage(page);
    		    //这个方法用来移动坐标原点的位置
                graphics.TranslateTransform(200, 200);
    			//这个方法用来旋转坐标轴
                graphics.RotateTransform(180);
    
                graphics.DrawLine(new XPen(XBrushes.AliceBlue), new XPoint(-200,0), new XPoint(200,0));
    
                graphics.DrawLine(new XPen(XBrushes.AliceBlue), new XPoint(0,200), new XPoint(0,-200));
    
    
                double radius = 60;
    
                XPoint[] points = new XPoint[6]
                {
                    new XPoint(){ X = 0,Y = radius },
                    new XPoint(){ X = Math.Sin(72*PAI/180)*radius,Y = Math.Sin(18*PAI/180)*radius },
                    new XPoint(){ X = Math.Sin(36*PAI/180)*radius,Y = -1*Math.Sin(54*PAI/180)*radius },
                    new XPoint(){ X = -1*Math.Sin(36*PAI/180)*radius,Y = -1*Math.Sin(54*PAI/180)*radius },
                    new XPoint(){ X = -1*Math.Sin(72*PAI/180)*radius,Y = Math.Sin(18*PAI/180)*radius},
                    new XPoint(){ X = 0,Y = radius }
                };
    
                graphics.DrawLines(new XPen(XColors.RoyalBlue),points);
    
                graphics.Save();
    
    
                doc.AddPage(page);
    
                doc.Save("../../../wdnmd.pdf");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    运行后可以得到
    在这里插入图片描述

    StepTwo:以原点为中心,以等比的半径画若干个五边形

    有了以上的代码,只需要准备一个半径数组即可
    如下:

    const double PAI = Math.PI;
            static void Main(string[] args)
            {
                PdfDocument doc = new PdfDocument();
    
                PdfPage page = new PdfPage(doc);
    
                XGraphics graphics = XGraphics.FromPdfPage(page);
    
                graphics.TranslateTransform(200, 200);
    
                graphics.RotateTransform(180);
    
                graphics.DrawLine(new XPen(XBrushes.AliceBlue), new XPoint(-200,0), new XPoint(200,0));
    
                graphics.DrawLine(new XPen(XBrushes.AliceBlue), new XPoint(0,200), new XPoint(0,-200));
    
                //等差/或等比都行
                double[] radius_list = new double[5]
                {
                  60,75,90,105,120
                };
    
                radius_list.ToList<double>().ForEach(item=> {
    
                    XPoint[] points = new XPoint[6]
                    {
                         new XPoint(){ X = 0,Y = item },
                         new XPoint(){ X = Math.Sin(72*PAI/180)*item,Y = Math.Sin(18*PAI/180)*item },
                         new XPoint(){ X = Math.Sin(36*PAI/180)*item,Y = -1*Math.Sin(54*PAI/180)*item },
                         new XPoint(){ X = -1*Math.Sin(36*PAI/180)*item,Y = -1*Math.Sin(54*PAI/180)*item },
                         new XPoint(){ X = -1*Math.Sin(72*PAI/180)*item,Y = Math.Sin(18*PAI/180)*item},
                         new XPoint(){ X = 0,Y = item }
                    };
    
                    graphics.DrawLines(new XPen(XColors.RoyalBlue), points);
    
                });
    
                graphics.Save();
    
    
                doc.AddPage(page);
    
                doc.Save("../../../wdnmd.pdf");
    
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述

    StepThree:填充数据

    假设有一组数据如下

    [100,20,66,33,55]
    [44,77,30,100,88]
    [66,88,77,50,20]
    
    • 1
    • 2
    • 3

    然后你要在以下两种方法中选择一种
    1.固定顶点数值
    2.以组中对位最大值为顶点数值(可以更充分的绘制)

    这里选择第二种
    接下来是确定组中各点在图中的位置
    因为点一定在原点到多边形顶点的连线上,且长度为self/Max*R
    所以可以确定点的具体坐标,

    这里直接省去计算的步骤,得出三组的坐标点为

    [(0,100/100*R),
    (-1*20/88*R*sin72,20/88*R*sin18),
    (-1*66/77*R*sin36,-1*66/77*R*sin54),
    (33/100*R*sin36,-1*33/100*R*sin54),
    (55/88*R*sin72,55/88*R*sin18)
    ]
    [(0,44/100*R),
    (-1*77/88*R*sin72,77/88*R*sin18),
    (-1*30/77*R*sin36,-1*30/77*R*sin54),
    (100/100*R*sin36,-1*100/100*R*sin54),
    (88/88*R*sin72,88/88*R*sin18)
    ]
    [(0,66/100*R),
    (-1*88/88*R*sin72,88/88*R*sin18),
    (-1*77/77*R*sin36,-1*77/77*R*sin54),
    (50/100*R*sin36,-1*50/100*R*sin54),
    (20/88*R*sin72,20/88*R*sin18)
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    StepFour:绘制多边形

    在确定了各个点的坐标位置后,直接调用graphics.DrawPolygon方法即可
    代码如下:

    const double PAI = Math.PI;
            static void Main(string[] args)
            {
                PdfDocument doc = new PdfDocument();
    
                PdfPage page = new PdfPage(doc);
    
                XGraphics graphics = XGraphics.FromPdfPage(page);
    
                graphics.TranslateTransform(200, 200);
    
                graphics.RotateTransform(180);
    
                graphics.DrawLine(new XPen(XBrushes.AliceBlue), new XPoint(-200,0), new XPoint(200,0));
    
                graphics.DrawLine(new XPen(XBrushes.AliceBlue), new XPoint(0,200), new XPoint(0,-200));
    
    
                /* double radius = 60;
    
                 XPoint[] points = new XPoint[6]
                 {
                     new XPoint(){ X = 0,Y = radius },
                     new XPoint(){ X = Math.Sin(72*PAI/180)*radius,Y = Math.Sin(18*PAI/180)*radius },
                     new XPoint(){ X = Math.Sin(36*PAI/180)*radius,Y = -1*Math.Sin(54*PAI/180)*radius },
                     new XPoint(){ X = -1*Math.Sin(36*PAI/180)*radius,Y = -1*Math.Sin(54*PAI/180)*radius },
                     new XPoint(){ X = -1*Math.Sin(72*PAI/180)*radius,Y = Math.Sin(18*PAI/180)*radius},
                     new XPoint(){ X = 0,Y = radius }
                 };
    
                 graphics.DrawLines(new XPen(XColors.RoyalBlue),points);*/
    
                //等差/或等比都行
                double[] radius_list = new double[5]
                {
                  60,75,90,105,120
                };
    
                radius_list.ToList<double>().ForEach(item=> {
    
                    XPoint[] points = new XPoint[6]
                    {
                         new XPoint(){ X = 0,Y = item },
                         new XPoint(){ X = Math.Sin(72*PAI/180)*item,Y = Math.Sin(18*PAI/180)*item },
                         new XPoint(){ X = Math.Sin(36*PAI/180)*item,Y = -1*Math.Sin(54*PAI/180)*item },
                         new XPoint(){ X = -1*Math.Sin(36*PAI/180)*item,Y = -1*Math.Sin(54*PAI/180)*item },
                         new XPoint(){ X = -1*Math.Sin(72*PAI/180)*item,Y = Math.Sin(18*PAI/180)*item},
                         new XPoint(){ X = 0,Y = item }
                    };
    
                    graphics.DrawLines(new XPen(XColors.RoyalBlue), points);
    
                });
    
    
    		
    			//假设以下是数据
                List<double[]> doubles = new List<double[]>()
                {
                    new double[]{100,20,66,33,55},
                    new double[]{44,77,30,100,88},
                    new double[]{ 66, 88, 77, 50, 20 }
                };
    
    			//寻找数据中每一列的最大值
                double maxOne = 0;
                double maxTwo = 0;
                double maxThree = 0;
                double maxFour = 0;
                double maxFive = 0;
                foreach(double[] temp in doubles){
                    maxOne = Math.Max(temp[0],maxOne);
                    maxTwo = Math.Max(temp[1], maxTwo);
                    maxThree = Math.Max(temp[2], maxThree);
                    maxFour = Math.Max(temp[3], maxFour);
                    maxFive = Math.Max(temp[4], maxFive);
                }
    
                doubles.ForEach(item => {
    				//根据同上的三角函数,确定各点的坐标
                    XPoint[] points = new XPoint[6]
                    {
                        new XPoint(0,item[0]/maxOne*120),
                        new XPoint(-1*item[1]/maxTwo*120*Math.Sin(72*PAI/180),item[1]/maxTwo*120*Math.Sin(18*PAI/180)),
                        new XPoint(-1*item[2]/maxThree*120*Math.Sin(36*PAI/180),-1*item[2]/maxThree*120*Math.Sin(54*PAI/180)),
                        new XPoint(item[3]/maxFour*120*Math.Sin(36*PAI/180),-1*item[3]/maxFour*120*Math.Sin(54*PAI/180)),
                        new XPoint(item[4]/maxFive*120*Math.Sin(72*PAI/180),item[4]/maxFive*120*Math.Sin(18*PAI/180)),
                        new XPoint(0,item[0]/maxOne*120)
                    };
    
                    graphics.DrawPolygon(new XPen(XColors.Red, 1), points);
                });
    
                
                
    
    
                graphics.Save();
    
    
                doc.AddPage(page);
    
                doc.Save("../../../wdnmd.pdf");
    
    
    
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107

    效果如下
    在这里插入图片描述

    StepFive:总结

    PdfSharp/Core的绘图方法很丰富,可以用来绘制比较精密的图形。
    同时,如果想要更进一步的绘制,最好将数据Model固定,弄一种固定格式,也可以借此展示更多信息。
    最后注意坐标点的计算需要用到一些三角函数,请不要忘光了。

  • 相关阅读:
    C#中委托和事件的使用总结
    什么样的人最适合做软件测试---喜欢找人帮忙办事的人
    LVS的简单介绍
    Pandas GroupBy 深度总结
    大一新生HTML期末作业个人介绍博客 使用html+css+javascript+jquery技术制作网页,含有动画,hover效果,含有表格布局
    HTML网页设计制作——响应式网页影视动漫资讯bootstrap网页(9页)
    栈、队列、矩阵的总结
    每日汇评:黄金从月度高点回落,但下行前进似乎有限
    6. Design A Web Crawler
    Easysearch Chart 0.2.0都有哪些变化
  • 原文地址:https://blog.csdn.net/jamenu/article/details/127646622