WPF如何绘制光滑连续贝塞尔曲线示例代码
作者:冷火虫 发布时间:2022-06-07 18:31:58
标签:wpf,连续,贝塞尔曲线
1.需求
WPF本身没有直接把点集合绘制成曲线的函数。可以通过贝塞尔曲线函数来绘制。
贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。当然在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等。
贝塞尔曲线类是:BezierSegment,三次贝塞尔曲线,通过两个控制点来控制开始和结束方向。
QuadraticBezierSegment,二次贝塞尔,通过一个控制点来控制弯曲方向。
本文使用的是三次。
图片来源 *
2.思路
大值思路是根据当前点,前一个点,后一个点,再后一个点。共四个点,来生成一条三次贝塞尔曲线。
曲线需要(开始点,结束点,控制点1,控制点2),图中标识的两个红色点即是控制点。
代码主要是计算两个红色的控制点。
先计算相邻点的中点【橙色】。
再将中点的连线平移到相邻的位置【蓝色点】,取得虚线,得到虚线的端点【红色】。
红色,即为控制点。
3.主要代码
/// <summary>
/// 获得贝塞尔曲线
/// </summary>
/// <param name="currentPt">当前点</param>
/// <param name="lastPt">上一个点</param>
/// <param name="nextPt1">下一个点1</param>
/// <param name="nextPt2">下一个点2</param>
/// <returns></returns>
private BezierSegment GetBezierSegment(Point currentPt, Point lastPt, Point nextPt1, Point nextPt2)
{
//计算中点
var lastC = GetCenterPoint(lastPt, currentPt);
var nextC1 = GetCenterPoint(currentPt, nextPt1); //贝塞尔控制点
var nextC2 = GetCenterPoint(nextPt1, nextPt2);
//计算相邻中点连线跟目的点的垂足
//效果并不算太好,因为可能点在两个线上或者线的延长线上,计算会有误差
//所以就直接使用中点平移方法。
//var C1 = GetFootPoint(lastC, nextC1, currentPt);
//var C2 = GetFootPoint(nextC1, nextC2, nextPt1);
//计算“相邻中点”的中点
var c1 = GetCenterPoint(lastC, nextC1);
var c2 = GetCenterPoint(nextC1, nextC2);
//计算【"中点"的中点】需要的点位移
var controlPtOffset1 = currentPt - c1;
var controlPtOffset2 = nextPt1 - c2;
//移动控制点
var controlPt1 = nextC1 + controlPtOffset1;
var controlPt2 = nextC1 + controlPtOffset2;
//如果觉得曲线幅度太大,可以将控制点向当前点靠近一定的系数。
controlPt1 = controlPt1 + 0 * (currentPt - controlPt1);
controlPt2 = controlPt2 + 0 * (nextPt1 - controlPt2);
var bzs = new BezierSegment(controlPt1, controlPt2, nextPt1, true);
return bzs;
}
效果图如下:
4.源码下载
http://xiazai.jb51.net/201804/yuanma/WPF-BezierSegment(jb51.net).rar
来源:http://www.cnblogs.com/chlm/p/8624696.html


猜你喜欢
- 使用匿名内部类课使代码更加简洁、紧凑,模块化程度更高。内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到。然而这
- 先看下效果:两种需求场景:1.广告页3s后跳转到首页2.短信验证码60s倒计时第一种的话,根据需求我们可以知道,我们想要的效果就是3s结束做
- 本文实例讲述了Android编程实现加载等待ProgressDialog的方法。分享给大家供大家参考,具体如下:显示progressDial
- 前言这里主要探讨中断常用的三个方法:interrupt()。在一个线程中调用需要中断现成的interrupt()方法,会对该线程发出信号,将
- 本文实例讲述了Java Swing实现简单的体重指数(BMI)计算器功能。分享给大家供大家参考,具体如下:BMI,Body Mass Ind
- JDK * :利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。CGlib * :利用AS
- 当我们需要与 NIO Channel 进行交互时, 我们就需要使用到 NIO Buffer, 即数据从 Buffer读取到 Channel
- 一、DataGridView不显示下面的新行通常DataGridView的最下面一行是用户新追加的行(行头显示*)。如果不想让用户新追加行即
- 前言通过adb shell input可以模拟android各种输入事件,比如文字、按键、触摸等等。adb shell inputUsage
- 一、封装类1.封装类概念Java中存在基础数据类型,但是在某些情况下,我们要对基础数据类型进行对象的操作,例如,集合中只能存对象,而不能存在
- 本文实例为大家分享了android实现简单仪表盘效果的具体代码,供大家参考,具体内容如下实现这个效果:中间的文字很好写,外层的进度条就需要自
- 静态变量初始化顺序1.简单规则首先先看一段最普遍的JAVA代码:public class Test{ public static Test1
- 最近学习了一下seata,由于nacos现在也挺火,于是学习了seata注册到nacos,然后集成springcloud1.nacos配置(
- 一、概述本文描述采用C#语言访问控制Tektronix TBS 2000B 系列示波器。接口协议采用NI-VISA。最近一个项目需要和一款示
- 目录前言实现思路其它总结前言本文将介绍如何通过使用EasyExcel自定义 * 实现在最终的Excel文件中新增一列自增的序号列,最终的效果
- Java实现基于Socket的简单通信 一.ServerSocket1.使用JavaFX写的小界面,方便观察客户端连接情况 &nb
- 目录查查询指定列查询所有列条件查询子查询根据业务逻辑添加条件连接查询增新增一条批量新增删改主要演示DynamicSql风格代码如何使用,基本
- 当我们在做前后端分离的开发时,在使用fetch交换数据的时候,提示Access-Control-Allow-Origin跨域问题,解决方案跟
- 本文实例讲述了Android编程开发之TextView控件用法。分享给大家供大家参考,具体如下:这里我们会讲讲常用控件的使用。在今后的大多数
- Google 发布的Material Design支持库,对我们的APP设计有很大的影响,如果重新设计APP,支持库应该直接用V4提升到V7