贝塞尔曲线是由法国数学家Pierre Bézier所发明,由此为计算机矢量图形学奠定了基础。它的主要意义在于无论是直线或曲线都能在数学上予以描述。贝塞尔曲线就是这样的一条曲线,它是依据四个位置任意的点坐标绘制出的一条光滑曲线。

线性公式

给定点P0、P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出:
且其等同于线性插值。

二次方公式

二次方贝兹曲线的路径由给定点P0、P1、P2的函数B(t)追踪:
TrueType字型就运用了以贝兹样条组成的二次贝兹曲线。

三次方公式

P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝兹曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;这两个点只是在那里提供方向资讯。P0和P1之间的间距,决定了曲线在转而趋进P3之前,走向P2方向的“长度有多长”。
曲线的参数形式为:
现代的成象系统,如PostScript、Asymptote和Metafont,运用了以贝兹样条组成的三次贝兹曲线,用来描绘曲线轮廓。

一般参数公式

阶贝兹曲线可如下推断。给定点P0、P1、…、Pn,其贝兹曲线即:
如上公式可如下递归表达: 用表示由点 P0、 P1、…、 Pn所决定的贝兹曲线。
用平常话来说,阶的贝兹曲线,即双阶贝兹曲线之间的插值。

公式说明

1.开始于P0并结束于Pn的曲线,即所谓的端点插值法属性。
2.曲线是直线的充分必要条件是所有的控制点都位在曲线上。同样的,贝塞尔曲线是直线的充分必要条件是控制点共线。
3.曲线的起始点(结束点)相切于贝塞尔多边形的第一节(最后一节)。
4.一条曲线可在任意点切割成两条或任意多条子曲线,每一条子曲线仍是贝塞尔曲线。
5.一些看似简单的曲线(如圆)无法以贝塞尔曲线精确的描述,或分段成贝塞尔曲线(虽然当每个内部控制点对单位圆上的外部控制点水平或垂直的的距离为时,分成四段的贝兹曲线,可以小于千分之一的最大半径误差近似于圆)。
6.位于固定偏移量的曲线(来自给定的贝塞尔曲线),又称作偏移曲线(假平行于原来的曲线,如两条铁轨之间的偏移)无法以贝兹曲线精确的形成(某些琐屑实例除外)。无论如何,现存的启发法通常可为实际用途中给出近似值。
上述是百度百科中关于贝塞尔曲线的详细描述,对于它的应用,最直观的,就像PS里的钢笔工具,今天,我将给出它的代码实现:
1,贝塞尔类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;namespace TestDemo
{unsafe class Bezier{Point PointCubicBezier(Point[] cp, float t){float ax, bx, cx, ay, by, cy, tS, tC;cx = 1.0f * (cp[1].X - cp[0].X);bx = 3.0f * (cp[2].X - cp[1].X) - cx;ax = cp[3].X - cp[0].X - cx - bx;cy = 1.0f * (cp[1].Y - cp[0].Y);by = 3.0f * (cp[2].Y - cp[1].Y) - cy;ay = cp[3].X - cp[0].Y - cx - by;tS = t * t;tC = tS * t;int x = (int)((ax * tC) + (bx * tS) + (cx * t) + cp[0].X);int y = (int)((ay * tC) + (by * tS) + (cy * t) + cp[0].Y);return new Point(x, y);}public Bitmap DrawBezier(Bitmap src, Point[] cp){Bitmap a = new Bitmap(src);int w = a.Width;int h = a.Height;BitmapData srcData = a.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);byte* p = (byte*)srcData.Scan0;float k = 0;k = 1.0f / (w - 1);Point temp;for (int i = 0; i < w; i++){temp = PointCubicBezier(cp, (float)i * k);p[temp.X * 3 + temp.Y * srcData.Stride] = 0;p[temp.X * 3 + 1 + temp.Y * srcData.Stride] = 0;p[temp.X * 3 + 2 + temp.Y * srcData.Stride] = 0;}a.UnlockBits(srcData);return a;}}
}

2,主界面代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;namespace TestDemo
{unsafe public partial class Form1 : Form{public Form1(){InitializeComponent();string startupPath = System.Windows.Forms.Application.StartupPath;curBitmap = new Bitmap(startupPath + @"\mask.png");//初始化pa = new Point(button1.Location.X - pictureBox1.Location.X + 13, button1.Location.Y - pictureBox1.Location.Y + 11);pb = new Point(button2.Location.X - pictureBox1.Location.X + 13, button2.Location.Y - pictureBox1.Location.Y + 11);pc = new Point(button3.Location.X - pictureBox1.Location.X + 13, button3.Location.Y - pictureBox1.Location.Y + 11);pd = new Point(button4.Location.X - pictureBox1.Location.X + 13, button4.Location.Y - pictureBox1.Location.Y + 11);pictureBox1.Image = (Image)bezier.DrawBezier(curBitmap, new Point[] { pa, pb, pc, pd });}#region  变量声明//当前图像变量private Bitmap curBitmap = null;private bool pointMoveStart = false;private Point movePoint;private Point pa;private Point pb;private Point pc;private Point pd;private Bezier bezier = new Bezier();#endregion#region Response#endregion#region MouseClickprivate void pictureBox1_MouseMove(object sender, MouseEventArgs e){if (pictureBox1.Image != null){label1.Text = "X:" + e.X;label2.Text = "Y:" + e.Y;}}private void button1_MouseDown(object sender, MouseEventArgs e){pointMoveStart = true;if (e.Button == MouseButtons.Left)movePoint = e.Location;}private void button1_MouseMove(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left && pointMoveStart){button1.Location = new Point(button1.Location.X + e.X - movePoint.X, button1.Location.Y + e.Y - movePoint.Y);}}private void button1_MouseUp(object sender, MouseEventArgs e){pointMoveStart = false;pa = new Point(button1.Location.X - pictureBox1.Location.X + 13, button1.Location.Y - pictureBox1.Location.Y + 11);pb = new Point(button2.Location.X - pictureBox1.Location.X + 13, button2.Location.Y - pictureBox1.Location.Y + 11);pc = new Point(button3.Location.X - pictureBox1.Location.X + 13, button3.Location.Y - pictureBox1.Location.Y + 11);pd = new Point(button4.Location.X - pictureBox1.Location.X + 13, button4.Location.Y - pictureBox1.Location.Y + 11);pictureBox1.Image = (Image)bezier.DrawBezier(curBitmap, new Point[] {pa, pb, pc, pd });}private void button2_MouseDown(object sender, MouseEventArgs e){pointMoveStart = true;if (e.Button == MouseButtons.Left)movePoint = e.Location;}private void button2_MouseMove(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left && pointMoveStart){button2.Location = new Point(button2.Location.X + e.X - movePoint.X, button2.Location.Y + e.Y - movePoint.Y);}}private void button2_MouseUp(object sender, MouseEventArgs e){pointMoveStart = false;pa = new Point(button1.Location.X - pictureBox1.Location.X + 13, button1.Location.Y - pictureBox1.Location.Y + 11);pb = new Point(button2.Location.X - pictureBox1.Location.X + 13, button2.Location.Y - pictureBox1.Location.Y + 11);pc = new Point(button3.Location.X - pictureBox1.Location.X + 13, button3.Location.Y - pictureBox1.Location.Y + 11);pd = new Point(button4.Location.X - pictureBox1.Location.X + 13, button4.Location.Y - pictureBox1.Location.Y + 11);pictureBox1.Image = (Image)bezier.DrawBezier(curBitmap, new Point[] { pa, pb, pc, pd });}private void button3_MouseDown(object sender, MouseEventArgs e){pointMoveStart = true;if (e.Button == MouseButtons.Left)movePoint = e.Location;}private void button3_MouseMove(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left && pointMoveStart){button3.Location = new Point(button3.Location.X + e.X - movePoint.X, button3.Location.Y + e.Y - movePoint.Y);}}private void button3_MouseUp(object sender, MouseEventArgs e){pointMoveStart = false;pa = new Point(button1.Location.X - pictureBox1.Location.X + 13, button1.Location.Y - pictureBox1.Location.Y + 11);pb = new Point(button2.Location.X - pictureBox1.Location.X + 13, button2.Location.Y - pictureBox1.Location.Y + 11);pc = new Point(button3.Location.X - pictureBox1.Location.X + 13, button3.Location.Y - pictureBox1.Location.Y + 11);pd = new Point(button4.Location.X - pictureBox1.Location.X + 13, button4.Location.Y - pictureBox1.Location.Y + 11);pictureBox1.Image = (Image)bezier.DrawBezier(curBitmap, new Point[] { pa, pb, pc, pd });}private void button4_MouseDown(object sender, MouseEventArgs e){pointMoveStart = true;if (e.Button == MouseButtons.Left)movePoint = e.Location;}private void button4_MouseMove(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left && pointMoveStart){button4.Location = new Point(button4.Location.X + e.X - movePoint.X, button4.Location.Y + e.Y - movePoint.Y);}}private void button4_MouseUp(object sender, MouseEventArgs e){pointMoveStart = false;pa = new Point(button1.Location.X - pictureBox1.Location.X + 13, button1.Location.Y - pictureBox1.Location.Y + 11);pb = new Point(button2.Location.X - pictureBox1.Location.X + 13, button2.Location.Y - pictureBox1.Location.Y + 11);pc = new Point(button3.Location.X - pictureBox1.Location.X + 13, button3.Location.Y - pictureBox1.Location.Y + 11);pd = new Point(button4.Location.X - pictureBox1.Location.X + 13, button4.Location.Y - pictureBox1.Location.Y + 11);pictureBox1.Image = (Image)bezier.DrawBezier(curBitmap, new Point[] { pa, pb, pc, pd });}#endregion}
}

结果图如下:

最后给出完整C#代码DEMO: 贝塞尔曲线.zip

图像算法---贝塞尔曲线相关推荐

  1. php 贝瑟尔曲线,贝塞尔曲线的应用详解

    简介 贝塞尔曲线是可以做出很多复杂的效果来的,比如弹跳球的复杂动画效果,首先加速下降,停止,然后弹起时逐渐减速的效果. 使用贝塞尔曲线常用的两个网址如下: 缓动函数: cubic-bezier: 如何 ...

  2. 贝塞尔曲线动画demo(仿美人相机效果)

    效果如图: 仿美人相机,手势滑动隐藏顶部view.为了方便讲解,将屏幕分为几个区域,如图: 在拖动过程中: 1.拖动距离小于minMoveDistance,贝赛尔曲线发生形变 2.拖动大于minMov ...

  3. 自定义View合辑(8)-跳跃的小球(贝塞尔曲线)

    为了加强对自定义 View 的认知以及开发能力,我计划这段时间陆续来完成几个难度从易到难的自定义 View,并简单的写几篇博客来进行介绍,所有的代码也都会开源,也希望读者能给个 star 哈 GitH ...

  4. Bézier曲线 和 Bézier曲面 ( 贝塞尔曲线 和 贝塞尔曲面 )

    Bézier曲线 定义 给定空间n+1个点的位置矢量Pi(i=0,1,2-),则Bezier参数曲线上各点坐标的插值公式是:P(t)=∑i=0nPiBi,n(t),t∈[0,1]P(t)=\sum_{ ...

  5. cic曲线是什么_贝塞尔曲线基本用法

    使用UIBezierPath可以创建基于矢量的路径,此类是Core Graphics框架关于路径的封装.使用此类可以定义简单的形状,如椭圆.矩形或者有多个直线和曲线段组成的形状等. UIBezierP ...

  6. android离散点贝塞尔曲线,离散点拟合曲线贝塞尔曲线B样条.ppt

    离散点拟合曲线贝塞尔曲线B样条 第三章 离散点绘制平面曲线;;不规则曲线(拟合曲线):指已知平面一些离散点的坐标,但曲线方程未知,需要人为设计曲线方程对这些点进行拟合形成的曲线.; 在用拟合方法建立曲 ...

  7. android 贝塞尔曲线点击区域,白话经典贝塞尔曲线及其在 Android 中的应用

    一.前言 谈到贝塞尔曲线可能不少人会浮现它高大上的数学公式.然而,在实际应用中,并不需要我们去完全理解或者推导出公式才能应用得上.实际情况是,即使真的只是一个学渣,我们应该也能很轻松的掌握贝塞尔曲线的 ...

  8. canvas贝塞尔曲线爱心_canvas实现高阶贝塞尔曲线(N阶贝塞尔曲线生成器)

    写在最前 由于原生的Canvas最高只支持到三阶贝塞尔曲线,那么我想添加多个控制点怎么办呢?(即便大部分复杂曲线都可以用3阶贝塞尔来模拟)与此同时,关于贝塞尔控制点的位置我们很难非常直观的清楚到底将控 ...

  9. 用html5的canvas画布绘制贝塞尔曲线

    查看效果:http://keleyi.com/keleyi/phtml/html5/7.htm 完整代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHT ...

最新文章

  1. Windows 11正式发布,所有用户均可免费升级,还支持安卓应用
  2. 使用 Bamboo 构建项目的 CICD 过程文档
  3. (7)操作系统安全机制一
  4. 科大星云诗社动态20210304
  5. 比尔盖茨的十句话,让你改变一生
  6. CSS3常用属性及用法
  7. linux定时任务的用法详解
  8. Eval绑定日期时,修改日期显示的格式
  9. Javascript基础回顾 之(二) 作用域
  10. javascript中的undefined 和 not defined
  11. VMware Workstation 12 Player之安装林耐斯-Linux Red Hat 7 -系统
  12. Android NIO(Noblocking I/O非阻塞I/O)小结
  13. Linux命令之进程的管理
  14. 千锋培训php怎么样,零基础学员真实感受 选择千锋PHP培训完成人生蜕变
  15. 求整数数组的最小值c语言,编程实现求一个整数数组num[]中的最大值与最小值并输出结果的程序...
  16. 跨交换机实现 VLAN 间路由
  17. 题解 2020级HAUT新生周赛(二)
  18. 在局域网内主动封堵BT下载使用
  19. 挂茶馆VIP问道教程
  20. 美的集团的命,智能家居来续?

热门文章

  1. 在.NET中进行AutoCAD二次开发(C#+ObjectArx) (二)
  2. 计算机加密怎么设置方法,如何设置电脑密码?手把手教你如何设置电脑Windows密码...
  3. 大起底神盾七号重疾险:赔两次价格还不贵,到底值不值?
  4. 安装Anaconda和配置环境
  5. 重庆APP开发价格费用如何计算?
  6. 使用计算机自适应测验大型测验,计算机自适应测验方法与流程
  7. 分享暄桐好作业之《临〈岁朝清供图〉》
  8. 【华为OD机试真题 JS】出错的或电路
  9. 科技部等6部门发文,推动AI场景创新;『精益副业』教程序员优雅做副业;『可扩展系统』设计全教程;人物动作数据集;前沿论文 | ShowMeAI资讯日报
  10. python富翁与穷人_穷人和富人就差1%的运气——python模拟社会财富分配游戏