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

相关推荐
我曾经是个程序员5 分钟前
C#集合排序的三种方法(List<T>.Sort、LINQ 的 OrderBy、IComparable<T> 接口)
开发语言·c#
cqths17 分钟前
.NET 9.0 的 Blazor Web App 项目、Bootstrap Blazor 组件库、自定义日志 TLog 使用备忘
数据库·c#·.net·web app
Mr.L705171 小时前
Maui学习笔记- SQLite简单使用案例02添加详情页
笔记·学习·ios·sqlite·c#
格林威3 小时前
BroadCom-RDMA博通网卡如何进行驱动安装和设置使得对应网口具有RDMA功能以适配RDMA相机
人工智能·数码相机·opencv·计算机视觉·c#
.NET骚操作5 小时前
Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到 Guid
ai·c#·.net·chats
xcLeigh6 小时前
WPF基础 | WPF 基础概念全解析:布局、控件与事件
c#·wpf
向阳121812 小时前
doris:Routine Load
数据库·c#·linq
C666688814 小时前
C#与AI的共同发展
开发语言·c#
CodeCraft Studio17 小时前
【实用技能】如何借助Excel处理控件Aspose.Cells,使用 C# 锁定 Excel 中的单元格
开发语言·c#·excel
pchmi17 小时前
C# OpenCV机器视觉:实现农作物病害检测
人工智能·opencv·c#·机器视觉·opencvsharp