【学习笔记】Windows GDI绘图(六)图形路径GraphicsPath详解(中)

news2024/11/24 9:29:44

上一篇【学习笔记】Windows GDI绘图(五)图形路径GraphicsPath详解(上)介绍了GraphicsPath类的构造函数、属性和方法AddArc添加椭圆弧、AddBezier添加贝赛尔曲线、AddClosedCurve添加封闭基数样条曲线、AddCurve添加开放基数样条曲线、基数样条如何转Bezier、AddEllipse添加椭圆、AddLine添加线段。

革命尚未成功,同志仍需努力!

文章目录

  • GraphicsPath方法
    • AddLines添加线段
    • AddPath附加路径
    • AddPie添加饼形
    • AddPolygon添加多边形
    • AddRectangle和AddRectangles 添加矩形
    • AddString添加字符串
    • SetMarkers设置标记
    • ClearMarkers清空标记
    • StartFigure开始新的图形
    • CloseAllFigures闭合所有图形、CloseFigure闭合当前图形

GraphicsPath

GraphicsPath方法

AddLines添加线段

原型:

public void AddLines (params System.Drawing.Point[] points);
public void AddLines (params System.Drawing.PointF[] points);

添加一系列的线段到GraphicsPath中。

// 定义三角形的顶点
Point[] points =
         {
            new Point(150,150),
            new Point(300,300),
            new Point(0,300),
            new Point(150,150)
          };

using (var myPath = new GraphicsPath())
{
    myPath.AddLines(points);

    e.Graphics.DrawPath(penRed, myPath);
}

通过点集绘制线段
AddLines

AddPath附加路径

原型:

public void AddPath (System.Drawing.Drawing2D.GraphicsPath addingPath, bool connect);

connect,当前路径与附加的路径是否相连
将指定的GraphicsPath附加到当前Path中

Point[] myArray =
         {
     new Point(120,120),
     new Point(240,240),
     new Point(0,240),
     new Point(120,120)
 };
GraphicsPath myPath = new GraphicsPath();
myPath.AddLines(myArray);

Point[] myArray2 =
         {
     new Point(120,100),
     new Point(20,20),
     new Point(220,20),
     new Point(120,100)
 };
GraphicsPath myPath2 = new GraphicsPath();
myPath2.AddLines(myArray2);

// Add the second path to the first path.
myPath.AddPath(myPath2, false);//各自独立

// Draw the combined path to the screen.
e.Graphics.DrawPath(penRed, myPath);

myPath.Reset();
myPath.AddLines(myArray);
myPath.AddPath(myPath2, true);//相连

myPath.Transform(new Matrix(1, 0, 0, 1, 400, 0));
e.Graphics.DrawPath(penLightGreen, myPath);

AddPath

AddPie添加饼形

原型:

public void AddPie (System.Drawing.Rectangle rect, float startAngle, float sweepAngle);
public void AddPie (int x, int y, int width, int height, float startAngle, float sweepAngle);
public void AddPie (float x, float y, float width, float height, float startAngle, float sweepAngle);

通过一个矩形、起始角度和扫描角度来角度一个饼形,与椭圆参数类似。

var rect = new Rectangle(100, 100, 200, 100);
using (var path = new GraphicsPath())
{
    //添加饼形 30°至150°
    path.AddPie(rect, 30, 120);
    e.Graphics.DrawPath(penRed, path);

    path.Reset();
    //150°至270°
    path.AddPie(rect, 30 + 120, 120);
    e.Graphics.DrawPath(penLightGreen, path);

    path.Reset();
    //30°到 270°(逆时针)
    path.AddPie(rect, 30, -120);
    e.Graphics.DrawPath(Pens.Chocolate, path);
}           
  

sweepAngle,正数,顺时针;负数,逆时针
AddPie

AddPolygon添加多边形

原型:

public void AddPolygon (System.Drawing.Point[] points);
public void AddPolygon (System.Drawing.PointF[] points);

定义点集,形成多边形

// 多边形顶点
Point[] myArray =
         {
     new Point(230, 200),
     new Point(400, 100),
     new Point(570, 200),
     new Point(500, 400),
     new Point(300, 400)
 };

using (var myPath = new GraphicsPath())
{
    //添加多边形
    myPath.AddPolygon(myArray);
    e.Graphics.DrawPath(penRed, myPath);
}

AddPolygon

AddRectangle和AddRectangles 添加矩形

原型:

public void AddRectangle (System.Drawing.RectangleF rect);
public void AddRectangle (System.Drawing.Rectangle rect);
public void AddRectangles (System.Drawing.Rectangle[] rects);
public void AddRectangles (params System.Drawing.RectangleF[] rects);

定义矩形和矩形集,添加到路径中。

var rect = new Rectangle(30, 50, 100, 80);

var rects = new RectangleF[]
{
    new RectangleF(150,50,80,60),
    new RectangleF(200,80,100,80)
};

using (var myPath = new GraphicsPath())
{                
    myPath.AddRectangle(rect);
    myPath.AddRectangles(rects);
    e.Graphics.DrawPath(penRed, myPath);
}

AddRectangle

AddString添加字符串

原型:

public void AddString (string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Point origin, System.Drawing.StringFormat? format);
public void AddString (string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.PointF origin, System.Drawing.StringFormat? format);
public void AddString (string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.Rectangle layoutRect, System.Drawing.StringFormat? format);
public void AddString (string s, System.Drawing.FontFamily family, int style, float emSize, System.Drawing.RectangleF layoutRect, System.Drawing.StringFormat? format);
参数说明
s待添加的文本
familyFontFamily字体名称
style文本样式,Bold-1,Italic-2,Regular-0,Strikeout-8,Underline-4
emSize文本高度,单位:像素
origin文本起始点,默认是左对齐时,是左上角
format指定文本格式信息,例如行距和对齐方式

这里先随便给个示例吧,估计关于绘制文本,可以另起一篇。

// Create a GraphicsPath object.
GraphicsPath myPath = new GraphicsPath();

// Set up all the string parameters.
string stringText = "我在学习GDI+";
FontFamily family = new FontFamily("Arial");
int fontStyle = (int)FontStyle.Italic;
int emSize = 38;//文本高度,像素
Point origin = new Point(200, 100);//文本开始绘制的左上角点

StringFormat format = new StringFormat(StringFormatFlags.NoWrap);
format.Alignment = StringAlignment.Center;//水平居中
format.LineAlignment = StringAlignment.Center; // 垂直居中

// Add the string to the path.
myPath.AddString(stringText,
    family,
    fontStyle,
    emSize,
    origin,
    format);

e.Graphics.FillPath(Brushes.Green, myPath);

//文本定位点
e.Graphics.FillEllipse(Brushes.Red, origin.X - 3, origin.Y - 3, 6, 6);

AddString

SetMarkers设置标记

原型:

public void SetMarkers ();

使用 SetMarkers 方法在 GraphicsPath 中的当前位置创建标记。使用 NextMarker 方法迭代路径中的现有标记。
标记用于分隔子路径组。两个标记之间可以包含一个或多个子路径。

[System.ComponentModel.Description("GraphicsPath的SetMarkers/ClearMarkers方法")]
public void Demo06_07(PaintEventArgs e)
{
    // Create a path and set two markers.
    GraphicsPath myPath = new GraphicsPath();
    myPath.AddLine(new Point(0, 0), new Point(50, 50));
    myPath.SetMarkers();
    Rectangle rect = new Rectangle(50, 50, 50, 50);
    myPath.AddRectangle(rect);
    myPath.SetMarkers();
    myPath.AddEllipse(100, 100, 100, 50);

    // Draw the path to screen.
    e.Graphics.DrawPath(new Pen(Color.Black, 2), myPath);

    var pathIterator =new GraphicsPathIterator(myPath);
    pathIterator.Rewind();

    var potins = myPath.PathPoints;
    var types = myPath.PathTypes;

    var height = 20;
    var markerIndex = 0;
    int startIndex;
    int endIndex;
    while(true)
    {
        var resultCount = pathIterator.NextMarker(out startIndex, out endIndex);
        if (resultCount == 0) break;
        //Marker信息
        e.Graphics.DrawString($"Marker {markerIndex}:  Start: {startIndex} End: {endIndex}",
            Font,
            Brushes.Red,
            200,
            height);
        height += 20;
        //每段Marker的点与类型信息
        for (int i = startIndex; i <= endIndex; i++)
        {
            e.Graphics.DrawString($"point {i}: ({potins[i].X},{potins[i].Y}) Type:{(int)types[i]}:{GetPathTypes((int)types[i])}",
                    Font,
                    Brushes.Black,
                    250,
                    height);
            height += 20;
        }
        markerIndex++;
    }

    myPath.ClearMarkers();
    pathIterator = new GraphicsPathIterator(myPath);
    pathIterator.Rewind();
    var count= pathIterator.NextMarker(out startIndex, out endIndex);
    //这里合成一个,0至19
}
/// <summary>
/// PathType转字符串
/// </summary>
/// <param name="pathType"></param>
/// <returns></returns>
private string GetPathTypes(int pathType)
{
    if (pathType == 0) return "0(起点)";
    List<string> typeStrs = new List<string>();
    while(true)
    {
        if(pathType >= 0x80)
        {
            typeStrs.Add("128(终点)");
            pathType -= 0x80;
        }
        else if (pathType >= 0x20)
        {
            typeStrs.Add("32(标记)");
            pathType -= 0x20;
        }
        else if (pathType >=0x7)
        {
            typeStrs.Add("7(屏蔽)");
            pathType -= 0x7;
        }
        else if(pathType >= 0x3)
        {
            typeStrs.Add("3(Bezier)");
            pathType -= 0x3;
        }
        else if (pathType >= 1)
        {
            typeStrs.Add("1(Line)");
            pathType -= 0x1;
        }
        if (pathType <= 0) break;
    }
    return string.Join("+",typeStrs.ToArray());
}

ClearMarkers清空标记

原型:

public void ClearMarkers ();

清除所有标记(Marker),合并为一个。

StartFigure开始新的图形

原型:

public void StartFigure ();

在不封闭当前图形(路径)下,新开一个图形,后续增加的路径将在此图形中。

CloseAllFigures闭合所有图形、CloseFigure闭合当前图形

原型:

public void CloseAllFigures ();
public void CloseFigure ();

CloseAllFigures :闭合该路径中所有开放的图形并开始一个新图形。它通过从端点到起点连接一条线来闭合每个开放图形。
CloseFigure:闭合当前图形并开始新图形。

// 创建含多个开放路径的图形
GraphicsPath myPath = new GraphicsPath();
myPath.StartFigure();
myPath.AddLine(new Point(10, 10), new Point(150, 10));
myPath.AddLine(new Point(150, 10), new Point(10, 150));
myPath.StartFigure();
myPath.AddArc(200, 200, 100, 100, 0, 90);
myPath.StartFigure();
Point point1 = new Point(300, 300);
Point point2 = new Point(400, 325);
Point point3 = new Point(400, 375);
Point point4 = new Point(300, 400);
Point[] points = { point1, point2, point3, point4 };
myPath.AddCurve(points);

// 绘制非封闭路径
e.Graphics.DrawPath(new Pen(Color.Green, 10), myPath);

// 封闭所有路径.
myPath.CloseAllFigures();

// 绘制封闭后路径
e.Graphics.DrawPath(new Pen(Color.Red, 1), myPath);


myPath = new GraphicsPath();
myPath.StartFigure();
myPath.AddLine(new Point(200, 10), new Point(400, 10));
myPath.AddLine(new Point(400, 10), new Point(400, 200));
myPath.CloseFigure();

e.Graphics.DrawPath(penRed, myPath);

CloseAllFigure

【学习笔记】Windows GDI绘图目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1689980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

营销短信XML接口对接发送示例

在现代社会中&#xff0c;通信技术日新月异&#xff0c;其中&#xff0c;短信作为一种快速、简便的通信方式&#xff0c;仍然在日常生活中占据着重要的地位。为了满足各种应用场景的需求&#xff0c;短信接口应运而生&#xff0c;成为了实现高能有效通信的关键。 短信接口是一种…

Linux--07---查看CPU、内存、磁盘

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 常用命令1.查看CPU使用率1.1 top 命令第一行是任务队列信息&#xff1a; top第二行为进程的信息 Tasks第三行为CPU的信息Mem:Swap 1.2 vmstat命令参数详解每个参数的…

(二)可视化面板:Grafana的安装

其他相关文章 &#xff08;一&#xff09;一套开源的系统监控报警框架&#xff1a;Prometheus安装 什么是grafana Grafana是一个面板(Dashboard),有着非常漂亮的图表和布局展示,功能齐全的度量仪表盘和图形编辑器。支持Graphite、zabbix、InfluxDB、Prometheus和OpenTSDB作为…

【ACM出版,下周召开】2024机器智能与数字化应用国际会议(MIDA2024)

会议日期&#xff1a;2024年5月30-31日 会议地点&#xff1a;中国-宁波 会议官网&#xff1a;https://www.iaast.cn/meet/home/Bx120sos 【大会主席】 Ljiljana Trajkovic 加拿大西蒙菲莎大学教授。 【论文出版与检索】 EI会议论文集-ACM出版 大会即日起围绕主题征集会…

K8s资源限制和三种探针

一 默写总结 1 pod 的组成 ① Pod 中有几种容器 init 初始化 &#xff0c;阻塞主容器运行&#xff0c;初始化后方可运行主容器 pause 基础容器&#xff1a; 提供network 的 namespace 和 共享存储 业务容器&#xff1a; 跑Pod 主应用 &#xff08;POD中跑什么&#xff1a;微…

22-LINUX--多线程and多进程TCP连接

一.TCP连接基础知识 1.套接字 所谓套接字(Socket)&#xff0c;就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端&#xff0c;提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲&#xff0c;套接字上联应用进程…

学习前端第四十三天(样式和类、元素大小和滚动、Window大小和滚动、坐标)

一、样式和类 1、className&#xff0c;classList elem.className 对应于 "class" 特性 <div id"box" class"a b" style"height: 20px;">box</div><script>const box document.getElementById("box");…

uniapp gaid-item组件增加角标的方法以及最新版本已删除角标参数的注意事项

在uniapp项目的开发中&#xff0c;列表组件gaid-item大家应该都是经常用的&#xff0c;其实组件上的角标用法也是很方便的&#xff0c;但是不熟悉的新手朋友&#xff0c;特别是用最新版的朋友可能都找不到角标方法的使用地方&#xff1a; 1.首先官方说明&#xff0c;在最新版本…

【Unity】免费的高亮插件——QuickOutline

除了常见的HighLightSystem来实现的高亮功能&#xff0c;其实还有很多的方法实现物体的高亮。 在 Unity资源商店 搜索OutLine&#xff0c;就会有很多免费好用的高亮插件。 下面介绍一下 QuickOutline这个插件&#xff0c;在 Unity资源商店 搜索到后&#xff0c;点击进去就可以…

【QGIS入门实战精品教程】13.1:导入带地理标签的航测照片

文章目录 一、数据准备二、导入带地理标签的航测照片三、导出点位shp四、生成航线一、数据准备 本实验数据位于13.1:导入带地理标签的航测照片.rar中,如下: 查看照片及相机参数信息,航测照片都带有相机参数、部分POS及地理坐标信息,如下所示: 二、导入带地理标签的航测照…

Java - AbstractQueuedSynchronizer

AQS简介 AQS全称AbstractQueuedSynchronizer&#xff0c;抽象队列同步器&#xff0c;是一个实现同步组件的基础框架。AQS使用一个int类型的成员变量state维护同步状态&#xff0c;通过内置的同步队列&#xff08;CLH锁、FIFO&#xff09;完成线程的排队工作&#xff0c;底层主…

AI大模型如何赋能智能座舱

AI 大模型如何赋能智能座舱 从上海车展上&#xff0c;我们看到由于智能座舱配置性价比较高&#xff0c;已经成为车企的核心竞争点之一&#xff0c;随着座舱硬件规模化装车&#xff0c;蔚小理、岚图、极狐等新势力开始注重座舱多模态交互&#xff0c;通过集成语音/手势/触控打造…

Vue速成学习笔记

这两天速成了一下Vue&#xff0c;在这里记录一下相关的笔记&#xff0c;之后有时间详细学Vue的时候再来回顾一下&#xff01; 一、Vue理解 1、Vue的核心特征&#xff1a;双向绑定。 在网页中&#xff0c;存在视图和数据。在Vue之前&#xff0c;需要使用JavaScript编写复杂的逻…

电脑同时配置两个版本mysql数据库常见问题

1.配置时&#xff0c;要把bin中的mysql.exe和mysqld.exe 改个名字&#xff0c;不然两个版本会重复&#xff0c;当然&#xff0c;在初始化数据库的时候&#xff0c;如果时57版本的&#xff0c;就用mysql57(已经改名的)和mysqld57 代替 mysql 和 mysqld 例如 mysql -u root -p …

Redis(十二) 持久化

文章目录 前言Redis实现数据的持久化Redis实现持久化的策略RDB手动触发RDB持久化操作自动触发RDB持久化操作 AOFAOF重写机制 前言 众所周知&#xff0c;Redis 操作数据都是在内存上操作的&#xff0c;而我们都知道内存是易失的&#xff0c;服务器重启或者主机掉电都会导致内存…

面试八股之MySQL篇4——事务篇

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

生命线上的高效传递:了解下医院内、外网文件交互方式的革新之路

在医院的日常运营中&#xff0c;普遍采用内外网隔离的建设方式。内网集信息管理、通讯协作、资源共享、业务流程管理于一身&#xff0c;承载了医院的医疗核心业务&#xff0c;如HIS&#xff08;医院信息系统&#xff09;、LIS&#xff08;实验室信息系统&#xff09;、EMR&…

如何灵活运用keil工具进行问题分析(1)— 解决日常程序卡死问题

前言 &#xff08;1&#xff09;如果有嵌入式企业需要招聘湖南区域日常实习生&#xff0c;任何区域的暑假Linux驱动实习岗位&#xff0c;可C站直接私聊&#xff0c;或者邮件&#xff1a;zhangyixu02gmail.com&#xff0c;此消息至2025年1月1日前均有效 &#xff08;2&#xff0…

山脉数组的峰顶索引 ---- 二分查找

题目链接 题目: 分析: 我们很明显, 可以从峰值位置将数组分成两段, 具有"二段性", 所以可以用二分查找因为arr是山峰数组, 不存在相等的情况如果arr[mid] > arr[mid 1], 说明mid的位置可能是峰值, 移动right mid如果arr[mid] < arr[mid 1], 说明mid的位置…

Java基础之异常(简单易懂)

异常 1.JAVA异常体系 &#xff08;1&#xff09;Throwable类(表示可抛)是所有异常和错误的超类&#xff0c;两个直接子类为Error和Exception,分别表示错误和异常;其中异常类Exception又分为运行时异常和非运行时异常&#xff0c;这两个异常有很大区别&#xff0c;运行时异常也…