C#基于SkiaSharp实现印章管理(5)

印章中最常见的特殊形状通常是五角星,空心、实心的都可能存在,本文学习并实现在印章内部绘制五角星形状。
  百度五角星的绘制方法,主要分为三种:
  1)五角星各点坐标固定,直接调用编程语言的绘制线条或绘制多边形的函数绘制五角星;
  2)利用编程语言中的旋转变换方式简化五角星绘图逻辑,如Python中的turtle模块,绘制五角星时就是绘直线->转向->绘直线,C#的GDI+和SkiaSharp模块都支持旋转变换,但相对Python而言则复杂得多;
  3)利用公式计算各点坐标,以五角星中某点为基准,计算其余九个点的坐标,然后调用编程语言的绘制线条或绘制多边形的函数绘制五角星。
  本文选择第三种方式,使用参考文献4中的计算公式计算各点坐标,下图也来自参考文献4。

  更新FigureType枚举,增加五角星类型,同时调整SealElement定义,为了与后续绘制文本时保持一致,增加Content字符串属性,将五角星10个点的坐标以特定格式保存在Content属性中,并在绘图时解析、绘制。
  创建新建五角星窗口(如下图所示),使用StartPoint属性保存起点坐标,用EndPoint的X属性保存五角星边长,其它设置保持不变。点击确定时基于参考文献4的计算公式计算各点坐标,不过测试过程中发现公式并不完全正确,使用基于公式计算参考文献2的各点坐标时个别点的坐标计算公式有误(F、G,同时各点的Y坐标都没有加起始点的Y坐标值),最终各点坐标计算方式如下代码所示:

csharp 复制代码
double angle18 = 18 * Math.PI / 180;
double angle36 = 36 * Math.PI / 180;
float sinValue = Convert.ToSingle(Math.Round(Math.Sin(angle18), 2));
float cosValue = Convert.ToSingle(Math.Round(Math.Cos(angle18), 2));
float sinValueLong36 = Convert.ToSingle(Math.Round(Math.Sin(angle36) * m_element.EndPoint.X, 2));
float cosValueLong36 = Convert.ToSingle(Math.Round(Math.Cos(angle36) * m_element.EndPoint.X, 2));
float sinValueLong = Convert.ToSingle(Math.Round(sinValue *m_element.EndPoint.X));
float cosValueLong = Convert.ToSingle(Math.Round(cosValue * m_element.EndPoint.X));
float sinValueLong2 = 2 * sinValueLong;
float cosValueLong2 = 2 * cosValueLong;

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append($"{m_element.StartPoint.X},{m_element.StartPoint.Y};");//A
stringBuilder.Append($"{m_element.StartPoint.X+ sinValueLong},{m_element.StartPoint.Y+ cosValueLong};");//C
stringBuilder.Append($"{m_element.StartPoint.X + sinValueLong + m_element.EndPoint.X},{m_element.StartPoint.Y + cosValueLong};");//E
stringBuilder.Append($"{m_element.StartPoint.X + sinValueLong+m_element.EndPoint.X-cosValueLong36},{m_element.StartPoint.Y + cosValueLong+ sinValueLong36};");//G
stringBuilder.Append($"{m_element.StartPoint.X + sinValueLong2*sinValue + sinValueLong2},{m_element.StartPoint.Y + sinValueLong2 * cosValue + cosValueLong2};");//I
stringBuilder.Append($"{m_element.StartPoint.X},{m_element.StartPoint.Y+cosValueLong2+sinValueLong2*cosValue-sinValueLong36};");//J
stringBuilder.Append($"{m_element.StartPoint.X - sinValueLong2 * sinValue - sinValueLong2},{m_element.StartPoint.Y + sinValueLong2 * cosValue + cosValueLong2};");//H
stringBuilder.Append($"{m_element.StartPoint.X - sinValueLong - m_element.EndPoint.X+ cosValueLong36},{m_element.StartPoint.Y + cosValueLong + sinValueLong36};");//F
stringBuilder.Append($"{m_element.StartPoint.X-sinValueLong-m_element.EndPoint.X},{m_element.StartPoint.Y+cosValueLong};");//D
stringBuilder.Append($"{m_element.StartPoint.X-sinValueLong},{m_element.StartPoint.Y+cosValueLong};");//B
stringBuilder.Append($"{m_element.StartPoint.X},{m_element.StartPoint.Y}");//A

绘制五角星时,最初采用canvas.DrawPoints函数,但测试时发现无论SKPaint的Style设置为Stroke或Fill,显示时都是按边框方式显示,暂时不清楚怎么回事,最终换为先创建SKPath,再调用AddPoly添加形状,最终调用canvas.DrawPath绘制形状的方式解决问题。
  最后是程序运行效果,包括显示边框和填充两种方式:

参考文献:

1\]https://learn.microsoft.com/zh-cn/dotnet/api/skiasharp?view=skiasharp-2.88 \[2\]https://www.cnblogs.com/bhnian/p/16343557.html \[3\]https://www.jb51.net/html5/676291.html \[4\]https://blog.csdn.net/L_Shaker/article/details/127313457 \[5\]https://blog.csdn.net/qq_42716155/article/details/105024837

相关推荐
~plus~18 分钟前
Harmony核心:动态方法修补与.NET游戏Mod开发
开发语言·jvm·经验分享·后端·程序人生·c#
htj1027 分钟前
C# 使用正则表达式
正则表达式·c#
~plus~28 分钟前
WPF八大法则:告别模态窗口卡顿
开发语言·经验分享·后端·程序人生·c#
就是有点傻36 分钟前
使用WPF的Microsoft.Xaml.Behaviors.Wpf中通用 UI 元素事件
c#
qq_297908011 小时前
C#报价系统陈列展示成本核算系统项目管理系统纸品非纸品报价软件
sqlserver·c#·.net·开源软件
CoderIsArt10 小时前
C#中的CLR属性、依赖属性与附加属性
c#
IGP915 小时前
20250606-C#知识:委托和事件
开发语言·c#
Kookoos16 小时前
ABP VNext 与 Neo4j:构建基于图数据库的高效关系查询
数据库·c#·.net·neo4j·abp vnext
张鱼小丸子_微辣16 小时前
.Net Framework 4/C# LINQ*
c#
..活宝..18 小时前
【Emgu CV教程】11.2、Scharr边缘检测
图像处理·计算机视觉·c#·emgu cv·图像分析