C# 开发电子印章制作工具 -- 附下载程序

前言 本人在业余时间,开发了一款电子印章制作软件。印章制作软件看似简单,其实不然。

比如对椭圆形印章而言,要求公司名称中的每一个字间隔相等,要求字的方向与椭圆曲线垂直。

要满足这些条件,需要复杂的计算,并且要有一定的几何学基础。软件界面如下:

点击下载发票印章生成工具。

本文主要讲述椭圆形印章制作思路,对于圆形印章 ,软件开发难度并不大。

椭圆印章要满足以下两个条件:

  1 公司名称字体间隔大小要一样。

  2 字体方向与对应的椭圆曲线是相切的。

下面分析如何通过程序满足这两点要求。

 1 计算椭圆的弧线长度

   假设公司名称占了椭圆220度边长,如何计算出220度弧线的长度? 肯定有数学公式可以计算。我没有用公式计算。我联想到了“微积分”的概念。可以将这一段弧线切成几千份小的弧线,把小的弧线段长度加起来就是总的长度。小的弧线段长度非常小,可以用两点之间的直线长度代替。

 假设将弧线分成n份,将这n个线段长度加起来就是弧线长度。

       /// <summary>
        /// 将弧线分成splitCount份,计算弧线上的点
        /// </summary>
        /// <param name="startDegree">弧线起始度数</param>
        /// <param name="splitCount">分成多少份</param>
        /// <returns></returns>
        List<PointDouble> GetDrawPoint(double startDegree, int splitCount)
        {
            double a = EllipseWidth / 2;
            double b = EllipseHeight / 2;

            List<PointDouble> result = new List<PointDouble>();

            Graphics g = Graphics;
            for (int i = 0; i < splitCount; i++)
            {
                double degree = startDegree + (i * CompanySpanDegree) / splitCount;
                double k = Math.Tan(ToArc(degree));
                List<PointDouble> intersections = CalIntersection(a, b, k);

                //Debug.WriteLine(string.Format("degree:{0}", degree));
                PointDouble ptDraw = new PointDouble();
                if (degree < 90)
                {
                    if (intersections[0].X < 0)
                    {
                        ptDraw = intersections[0];
                    }
                    else if (intersections[0].X > 0)
                    {
                        ptDraw = intersections[1];
                    }
                    else
                    {
                    }
                }
                else if (degree > 90)
                {
                    if (intersections[0].X > 0)
                    {
                        ptDraw = intersections[0];
                    }
                    else if (intersections[0].X < 0)
                    {
                        ptDraw = intersections[1];
                    }
                    else
                    {
                    }
                }
                else
                {
                    if (intersections[0].Y < 0)
                    {
                        ptDraw = intersections[0];
                    }
                    else
                    {
                        ptDraw = intersections[1];
                    }
                }

                result.Add(ptDraw);
            }

            return result;
        }

2 确定每个文字的坐标。

弧线总长度计算处理后,就可以算出每个文字占用的弧线长度,根据每个文字占用的弧线长度就可以计算出文字的坐标。

        List<PointDouble> CalDrawPoint(float startDegree, int txtCount)
        {
            List<double> listLenPart = new List<double>();
            List<PointDouble> listPoint = GetDrawPoint(startDegree, 10000);
            //计算弧线长度
            double arcLen = CalPointLen(listPoint, listLenPart);
            //每个文字占用的弧线长度
            double txtSpanPer = arcLen / (txtCount - 1);

            //计算文字对应的点
            List<PointDouble> result = new List<PointDouble>();
            result.Add(listPoint[0]);

            double lenSpanCal = 0;
            for (int i = 0; i < listLenPart.Count; i++)
            {
                double n = listLenPart[i];
                lenSpanCal += n;
                if (lenSpanCal >= txtSpanPer)
                {
                    result.Add(listPoint[i + 1]);
                    lenSpanCal = 0;
                }
            }

            if (result.Count < txtCount)
                result.Add(listPoint.Last());

            Debug.Assert(result.Count == txtCount);
            return result;
        }

3 计算文字的旋转角度

 确定了文字的坐标后,就可以计算出该点对应的切线,从而求出切线角度。切线公式如下:

 计算切线坐标源码如下:

       /// <summary>
        /// 计算椭圆切线的角度
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        float CalTangentLineDegree(float x, float y)
        {
            if (y == 0)
                return 90;

            float a = EllipseWidth / 2;
            float b = EllipseHeight / 2;
            float k = -b * b * x / (a * a * y);
            float result = (float)Math.Atan(k);
            result = (float)ToDegree(result);
            return result;
        }

文字的坐标和旋转角度确定后,后续处理就水到渠成:

 程序界面截图:

 

 

专注C#、C++。擅长WPF、WinForm、QT等技术。 研究ofd多年,开发了一些列产品。 技术交流QQ群:618168615。
原文地址:https://www.cnblogs.com/yuanchenhui/p/seal-maker.html