通过三阶贝塞尔曲线拟合1/4圆

三阶贝塞尔曲线拟合1/4圆

根据贝塞尔曲线的知识,我们知道三阶贝塞尔曲线的参数方程如下,其中A、B、C、D为四个控制点坐标,P(t)表示曲线上的每一点。

因为要模拟1/4圆,所以通过P(0)和P(1)的切线方向,应该按照下图所示位置安放。其中AB为水平方向,DC为垂直方向,并且线段长度|AB| = |DC| = h。

那么这个问题实际上,就转换为计算出合理的h值,使得半径|OJ| = 1,也即J点刚好在圆弧上。

根据贝塞尔曲线的对称性,不难想出J点在P(0.5)处,代入公式即可求得:

同样的结论,也可以直接由贝塞尔曲线的几何图形特征来推定,也即:

所以也可以再次确认P(0.5)和J是同一点。

代入四个控制点坐标A(0, 1),B(h, 1),C(1, h)和D(1, 0),可以求解P(0.5)点坐标如下:

根据圆形方程定义,可以拟出下面方程:

从而求解出h的值为:

所以,可以最终求解出三阶贝塞尔曲线模拟1/4圆的参数方程P(t)定义如下:

另一方面,该方程描述的曲线与真实1/4圆有多大差异呢?下面就针对这个问题进行数值求解。

采用t = 0.0到1.0,步进值0.01,求解每个点到原点的距离与半径1的差异。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

double bezier3(double a, double b, double c, double d, double t)
{
	double nt = 1.0 - t;
	double nt2 = nt * nt;
	double nt3 = nt * nt * nt;
	double t2 = t * t;
	double t3 = t * t * t;

	return (a * nt3 + b * 3.0 * nt2 * t + c * 3.0 * nt * t2 + d * t3);
}

int main()
{
        double t, a;
        double d, e;
        double max_e = 0.0, min_e = 1.0;

        double x, y;
        double h = (sqrt(2) - 1.0) * 4.0 / 3.0;
        for(t = 0.0; t < 1.01; t+=0.01)
        {
                x = bezier3(0, h, 1, 1, t);
                y = bezier3(1, 1, h, 0, t);
                d = sqrt(x * x + y * y);
                e = d - 1.0;

                a = atan2(y, x);
                a = a * 180.0 / 3.1415926;

                if(max_e < e) max_e = e;
                if(min_e > e) min_e = e;
                printf("%4.1f, %f\n", a, e);
        }
        printf("max_e = %f, min_e = %f\n", max_e, min_e);
	return 0;
}

输出结果如下:

90.0, 0.000000
89.1, 0.000003
88.1, 0.000010
87.2, 0.000022
86.2, 0.000037
85.3, 0.000054
84.4, 0.000073
83.4, 0.000092
82.5, 0.000113
81.6, 0.000133
80.7, 0.000153
79.7, 0.000172
78.8, 0.000190
77.9, 0.000206
77.0, 0.000221
76.1, 0.000234
75.2, 0.000246
74.3, 0.000255
73.4, 0.000263
72.5, 0.000268
71.6, 0.000271
70.7, 0.000273
69.8, 0.000272
68.9, 0.000269
68.0, 0.000265
67.1, 0.000259
66.2, 0.000251
65.3, 0.000242
64.4, 0.000232
63.5, 0.000220
62.6, 0.000208
61.8, 0.000194
60.9, 0.000181
60.0, 0.000166
59.1, 0.000152
58.2, 0.000137
57.3, 0.000123
56.5, 0.000108
55.6, 0.000094
54.7, 0.000081
53.8, 0.000068
52.9, 0.000056
52.0, 0.000045
51.2, 0.000035
50.3, 0.000026
49.4, 0.000018
48.5, 0.000012
47.6, 0.000007
46.8, 0.000003
45.9, 0.000001
45.0, 0.000000
44.1, 0.000001
43.2, 0.000003
42.4, 0.000007
41.5, 0.000012
40.6, 0.000018
39.7, 0.000026
38.8, 0.000035
38.0, 0.000045
37.1, 0.000056
36.2, 0.000068
35.3, 0.000081
34.4, 0.000094
33.5, 0.000108
32.7, 0.000123
31.8, 0.000137
30.9, 0.000152
30.0, 0.000166
29.1, 0.000181
28.2, 0.000194
27.4, 0.000208
26.5, 0.000220
25.6, 0.000232
24.7, 0.000242
23.8, 0.000251
22.9, 0.000259
22.0, 0.000265
21.1, 0.000269
20.2, 0.000272
19.3, 0.000273
18.4, 0.000271
17.5, 0.000268
16.6, 0.000263
15.7, 0.000255
14.8, 0.000246
13.9, 0.000234
13.0, 0.000221
12.1, 0.000206
11.2, 0.000190
10.3, 0.000172
 9.3, 0.000153
 8.4, 0.000133
 7.5, 0.000113
 6.6, 0.000092
 5.6, 0.000073
 4.7, 0.000054
 3.8, 0.000037
 2.8, 0.000022
 1.9, 0.000010
 0.9, 0.000003
-0.0, 0.000000
max_e = 0.000273, min_e = 0.000000

从输出结果分析可以看到,误差均为向着圆弧外凸,0度到45度一段,45度到90度一段。

在0度、45度和90度为最小误差0.000000,在19.3度和70.7度达到最大误差为0.000273,基本上非常接近1/4圆弧了。

以上,即为三阶贝塞尔曲线模拟1/4圆弧的全部内容。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 16:51:31

通过三阶贝塞尔曲线拟合1/4圆的相关文章

平滑曲线生成:贝塞尔曲线拟合

平滑曲线生成是一个很实用的技术 很多时候,我们都需要通过绘制一些折线,然后让计算机平滑的连接起来,或者是生成一些平滑的面 这里介绍利用一种贝塞尔曲线拟合的方法,先给出我们最终的效果     图1 .折线拟合                                                                      图2.多边形拟合(封闭的折线) 继续阅读本文之前,你需要先掌握贝塞尔曲线的基本知识,这个网上资料很多,这里直接给出源代码 //count为插入点数, ou

贝塞尔曲线开发的艺术

贝塞尔曲线开发的艺术 一句话概括贝塞尔曲线:将任意一条曲线转化为精确的数学公式. 很多绘图工具中的钢笔工具,就是典型的贝塞尔曲线的应用,这里的一个网站可以在线模拟钢笔工具的使用: http://bezier.method.ac/ 贝塞尔曲线中有一些比较关键的名词,解释如下: 数据点:通常指一条路径的起始点和终止点 控制点:控制点决定了一条路径的弯曲轨迹,根据控制点的个数,贝塞尔曲线被分为一阶贝塞尔曲线(0个控制点).二阶贝塞尔曲线(1个控制点).三阶贝塞尔曲线(2个控制点)等等. 要想对贝塞尔曲

三次贝塞尔曲线画圆的方法。

上一篇说的仿58同城loadingview的项目.中有一个利用贝塞尔曲线进行绘制圆的步骤,这个贝塞尔曲线理论挺复杂,特此单独说一下所知的和能用到的. 比方上一个loadingView的项目中.要用到Path.cubic()来使用贝塞尔曲线画一个圆,那么首先要了解的是 Path.cubic()方法的定义: void cubicTo(float x1,float y1,float x2,float y2,float x3,float y3) Add a cubic bezier from the l

自定义视图与贝塞尔曲线

APK下载地址 1.贝塞尔曲线 以下公式中: B(t)为t时间下 点的坐标: P0为起点,Pn为终点,Pi为控制点 一阶贝塞尔曲线(线段): 意义:由 P0 至 P1 的连续点, 描述的一条线段 二阶贝塞尔曲线(抛物线): 原理:由 P0 至 P1 的连续点 Q0,描述一条线段. 由 P1 至 P2 的连续点 Q1,描述一条线段. 由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线. 经验:P1-P0为曲线在P0处的切线. 三阶贝塞尔曲线: 通用公式: 高阶贝塞尔曲线: 4阶曲线:

安卓自定义 View 进阶:贝塞尔曲线

在上一篇文章Path之基本图形中我们了解了Path的基本使用方法,本次了解Path中非常非常非常重要的内容-贝塞尔曲线. 一.Path常用方法表 为了兼容性(偷懒) 本表格中去除了在API21(即安卓版本5.0)以上才添加的方法.忍不住吐槽一下,为啥看起来有些顺手就能写的重载方法要等到API21才添加上啊.宝宝此刻内心也是崩溃的. 作用相关方法备注 移动起点moveTo移动下一次操作的起点位置 设置终点setLastPoint重置当前path中最后一个点位置,如果在绘制之前调用,效果和moveT

Android自定义View进阶 - 贝塞尔曲线

Path之贝塞尔曲线 作者微博: @GcsSloop [本系列相关文章] 在上一篇文章Path之基本图形中我们了解了Path的基本使用方法,本次了解Path中非常非常非常重要的内容-贝塞尔曲线. 一.Path常用方法表 为了兼容性(偷懒) 本表格中去除了在API21(即安卓版本5.0)以上才添加的方法.忍不住吐槽一下,为啥看起来有些顺手就能写的重载方法要等到API21才添加上啊.宝宝此刻内心也是崩溃的. 作用 相关方法 备注 移动起点 moveTo 移动下一次操作的起点位置 设置终点 setLa

Android -- 贝塞尔实现水波纹动画(划重点!!)

1,昨天看到了一个挺好的ui效果,是使用贝塞尔曲线实现的,就和大家来分享分享,还有,在写博客的时候我经常会把自己在做某种效果时的一些问题给写出来,而不是像很多文章直接就给出了解决方法,这里给大家解释一下,这里写出我遇到的一些问题不是为了凑整片文章的字数,而是希望大家能从根源下知道它是怎么解决的,而不是你直接百度搜索这个问题解决的代码,好了,说了这么多,只是想告诉大家,我后面会在过程中提很多问题(邪恶脸,嘿嘿嘿),好吧,来看看今天的效果: 2,what is the fuck?,这就是你说的很好看

Android 贝塞尔曲线实现QQ拖拽清除效果

纯属好奇心驱动写的一个学习性Demo,效果如下: 这个小功能最重要的点在于起始点和触摸点之间的连接线绘制,它并不是一条单纯的直线,而是中间细两头粗的一条不规则的Path,而这个中间向内弯曲的效果正是一条贝塞尔曲线,中间这个Path是由两条贝塞尔曲线和两条直线组成.看下图: 两个带圆弧的线就是由三点确认的一个贝塞尔曲线: 在Android已经有提供画贝塞尔曲线的接口,三个点传进去,效果就出来了. 贝塞尔曲线是用三个或多个点来确定的一条曲线,它在图形图像学中有相当重要的地位,Path中也提供了一些方

OpenGL绘制简单的参数曲线——三阶Bezier曲线(二)

今天我们来介绍三次Bezier曲线,这曲线网上资料非常多,我这里只是简单介绍下原理. 在二维空间中(三维也类似),给定n+1个点P0.P1.... .Pn.参数t的n次的Bezier曲线是: 图1 我们根据上面式子可以推出一阶.二阶.三阶贝塞尔曲线,下面是一阶贝塞尔曲线: 图2 下面是二阶贝塞尔曲线,表示的是从P0P1线段取Q0,P1P2线段取Q1,每一个Q0Q1都是曲线的切向量: 图3 下面是三阶贝塞尔曲线,表示的是从P0P1线段取Q0,P1P2线段取Q1,P2P3线段取Q2,再从Q0Q1取R