发信人: william@cis_nctu (何陋居主), 信区: programming
标 题: [转载] Hermite 与 Bezier 曲线的绘制
发信站: 交大资科_BBS (May 25 00:32:41 1995)
转信站: cis_nctu
From: Chi'u I-Nan * Area: 90 C 语言
To: All
Date: 03 May 95 22:37:26
Subj: Hermite 与 Bezier 曲线的绘制
**********************************************************************
* Hermite与Bezier曲线绘制方法研究
*
* 作者:邱奕南 (Chi'u I-Nan)
*
* 版权声明:以下文章内容本人仅同意供BBS 站上流传学习,但必须完整流传 *
* (含版权声明及程序),其余权利一概保留。任何未经本人同意 *
* ,将本文贩卖、刊登、节录、或其它一切侵害本人著作权之行为 *
* 者,皆需负担刑事责任及民事赔偿责任。 *
**********************************************************************
Hermite及Bezier曲线为三度空间曲线的常用表示法,以下我们先说明一
下这两个曲线的定义:
1.Hermite曲线
Hermite曲线为给定两端点及两端点向量所得的三次曲线。令三次曲线:
3 2
x(t) = Ax * t + Bx * t + Cx * t + d
3 2
y(t) = Ay * t + By * t + Cy * t + d
且令给定的两端点为(x1,y1)、(x2,y2),以及两端点向量(xr1,yr1)、(xr2,yr2),
则:
x(0) = x1, y(0) = y1
x(1) = x2, y(1) = y2
x'(0) = xr1, y'(0) = yr1
x'(1) = xr2, y'(1) = yr2
绘出(x(t),y(t)),0<=t<=1,即为Hermite曲线。
2.Bezier曲线
Bezier曲线为给定两端点及另两参考点所得的三次曲线,它可说是Hermite
曲线的另一种表示方式。假设两端点为P1、P2,以及两参考点Pr1、Pr2,则
Bezier曲线换算成Hermite曲线的方式为:
R1 = 3*(Pr1-P1)
R2 = 3*(P2-Pr2)
R1、R2即为Hermite曲线的两端点向量。
由于Bezier曲线和Hermite曲线可以说是相同的,因此以下之说明我们便以
Hermite曲线为主。由Hermite曲线的定义,首先我们必须求出Ax,Bx...等值。
由定义中的条件:
x(0) = x1, x(1) = x2, x'(0) = xr1, x'(1) = xr2
以及
2
x'(t) = 3 * Ax * t + 2 * Bx * t + Cx
可得:
┌ 0 0 0 1 ┐┌ Ax ┐ ┌ x1 ┐
│ 1 1 1 1 ││ Bx │=│ x2 │
│ 0 0 1 0 ││ Cx │ │ xr1 │
└ 3 2 1 0 ┘└ Dx ┘ └ xr2 ┘
解之得:
┌ Ax ┐ ┌ 2 -2 1 1 ┐┌ x1 ┐
│ Bx │=│ -3 3 -2 1 ││ x2 │
│ Cx │ │ 0 0 1 0 ││ xr1 │
└ Dx ┘ └ 1 0 0 0 ┘└ xr2 ┘
因此
x(t) = (2*t^3 - 3*t^2 + 1) * x1 + (-2*t^3 + 3*t^2) * x2 +
(t^3 - 2*t^2 + t) * xr1 + (t^3 - t^2) * xr2
同理
y(t) = (2*t^3 - 3*t^2 + 1) * y1 + (-2*t^3 + 3*t^2) * y2 +
(t^3 - 2*t^2 + t) * yr1 + (t^3 - t^2) * yr2
上述的公式中,由于t的值是介于0与1之间,这对于我们在实际绘图上较不
方便,而且运算速度也比较慢。因此假设我们以n条直线来仿真Hermite曲线,
则我们必须将t值化成整数,使它成为0<=t<=n(注意n条连续直线需有n+1个点)。
令i=n*t代入上述公式,化简后可得:
x(i) = (m1*x1 + m2*x2 + m3*xr1 + m4*xr2) / n^3
y(i) = (m1*y1 + m2*y2 + m3*yr1 + m4*yr2) / n^3
其中
m1 = 2*i^3 - 3*n*i^2 + n^3 , 0 <= i <= n
m2 = -2*i^3 + 3*n*i^2
m3 = i^3 - 2*n*i^2 + n^2*i
m4 = i^3 - n*i^2
如此我们便能很方便地求出仿真直线的各端点。然而上述公式中的乘法仍相当
多,对于m1~m4的计算上至少需5次乘法、2次移位乘法和6次加法(或4次乘法、
3次移位乘法和7次加法),在计算上仍然会浪费相当多时间(PC上的乘法约为
加法的近20倍,移位乘法则和加法相当),因此有必要再予以化简。如何简化
呢?由上述公式可发现,主要的乘法来自于i^3的计算,因此欲将之简化的最简
单的方式便是由前一个m1~m4值来求得后一个m1~m4值,藉此消减掉这个三次
方值的运算:
m1(i+1) = m1(i) + 6*i^2 + 6*i + 2 - 3*n*(2*i+1)
m2(i+1) = m2(i) - 6*i^2 - 6*i - 2 + 3*n*(2*i+1)
m3(i+1) = m3(i) + 3*i^2 + 3*i + 1 - 2*n*(2i+1) + n^2
m4(i+1) = m4(i) + 3*i^2 + 3*i + 1 - n*(2*i+1)
现在便是要化简各式中后面的计算项次。由于这些项次有相当多的重复,故可
将之写成:
m1(i+1) = m1(i) + a
m2(i+1) = m2(i) - a
m3(i+1) = m3(i) + d - c + n^2
m4(i+1) = m4(i) + d
a = 2*b - 3*c
b = 3*i^2 + 3*i + 1
c = n*(2*i+1)
d = b-c
再进一步简化为:
e = 2*i + 1
c = n*e
b = 3*i^2 + 3*i + 1
= (3*i+1)*i + (2*i+1)
= (e+i)*i + e
整理一下成为(依计算顺序):
e = 2*i + 1
b = (e+i)*i + e
c = n*e
d = b-c
m4 = m4 + d
f = d-c
m3 = m3 + f + n^2
a = d + f
m2 = m2 - a
m1 = m1 + a
共计2次乘法、1次移位乘法和11次加法,等于是以两次加法代替了两次乘法,
其速度必然较快。记得m1~m4的初值为:
m1(0) = n^3
m2(0) = m3(0) = m4(0) = 0
接下来我们要探讨一下模拟线数n的问题。倒底取多少模拟线数较为恰当?
采用的仿真线数太少,曲线将不够平滑,但若模拟线数太多,曲线绘制速度又
会太慢。据作者实际的测试,一般取n=20以上曲线便已相当平滑,但对于弯度
太大的曲线,其转折处仍约略可见,不过并不严重。由于在绘制曲线时,大都
以整数来运算(为求速度),因此仿真线数最好不要超出32,以避免运算结果
超出整数运算的值域。以下便是Hermite曲线和Bezier曲线的绘制程式:
#define Iterative 24 /* 曲线仿真的线数(必须小于32) */
#define Iterative2 (Iterative*Iterative)
#define Iterative3 (Iterative2*Iterative)
void DrawHermiteCurve(int x1,int y1,int x2,int y2,int xr1,int yr1,
int xr2,int yr2)
{
/* ------------------------------------------------------------
作用:画出Hermite曲线
输入:x1,y1,x2,y2 = 曲线端点
xr1,yr1,xr2,yr2 = 曲线两参考向量
作者:邱奕南 Chi'u I-Nan
------------------------------------------------------------ */
int i, oldx, oldy, m1, m2, m3, m4, x, y, k1, k2;
oldx = x1;
oldy = y1;
m1 = Iterative3;
m2 = m3 = m4 = 0;
for (i=0; i<Iterative; i++) /* 用Iterative条直线仿真 */
{
k1 = (i << 1) + 1;
k2 = (k1+i)*i + k1;
m4 += (k2 -= (k1 *= Iterative));
m3 += (k1 = k2 - k1) + Iterative2;
m2 -= (k2 += k1);
m1 += k2;
x = (int) (((long) x1*m1 + (long) x2*m2 + (long) xr1*m3 +
(long) xr2*m4) / Iterative3);
y = (int) (((long) y1*m1 + (long) y2*m2 + (long) yr1*m3 +
(long) yr2*m4) / Iterative3);
DrawLine(oldx,oldy,x,y);
oldx = x;
oldy = y;
}
}
void DrawBezierCurve(int x1,int y1,int x2,int y2,int xr1,int yr1,
int xr2,int yr2)
{
/* ------------------------------------------------------------
作用:画出Bezier曲线
输入:x1,y1,x2,y2 = 曲线端点
xr1,yr1,xr2,yr2 = 曲线两参考点
作者:邱奕南 Chi'u I-Nan
------------------------------------------------------------ */
DrawHermiteCurve(x1,y1,x2,y2,3*(xr1-x1),3*(yr1-y1),3*(x2-xr2),3*(y2-yr2));
}
* 青衫诗客 -- 小邱 *
-- Via 中文银版快信 V2.28C
! Origin: 档案货柜, 欢迎您来挖宝, 28800 BPS, 04-230-2080; (90:2010/622)
________________________________________
-- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- --
≡ 何陋居 ≡ 中学生以伏案读书为主, 大学生则应起而高瞻远瞩。 Whitehead.
-- -- -- -- -- -- -- -- -- -- -- -- -- --
-- -- -- -- -- -- -- -- -- -- -- --
分享到:
相关推荐
本主题主要关注三种常见的曲线类型:Bezier曲线、三次B样条(B-Spline)以及Hermite曲线,这些都是在MFC(Microsoft Foundation Classes)环境中实现的。下面将分别对这三种曲线进行详细讲解,并探讨它们在MFC下的...
本项目提供的"matlab_按输入点绘制三次曲线、Hermite曲线、Bezier曲线和B样条曲线"是一个实用的工具,它允许用户交互式地定义控制点并观察不同曲线类型的变化。 三次曲线是一种常见的数学曲线,通常用于平滑数据或...
在计算机图形学中,曲线是描绘形状和路径的重要工具,Hermite曲线和Bezier曲线是两种常见的非均匀有理B样条(NURBS)曲线。这篇文章将详细讲解这两种曲线的理论基础、实现原理以及如何在VC6.0 MFC环境中进行编程实现...
本项目聚焦于三种常见的曲线表示方法:Hermite曲线、Bezier曲线以及三次B样条曲线,并通过Microsoft Foundation Classes (MFC)进行实现。MFC是微软提供的一种C++类库,用于构建Windows应用程序,它简化了Windows API...
对于压缩包中的"Bezier"文件,可能包含的是一个C++程序,用于绘制Bezier曲线。这个程序可能包括控制点的设置、De Casteljau算法的实现以及图形界面的交互逻辑,如鼠标点击修改控制点位置等。 总的来说,理解并实现...
每个三次Bezier曲线由四个控制点决定,前两个和后两个点分别与相邻样条的端点相接,保证了连续性。 Hermite插值曲线则是另一种基于控制点的曲线形式,它允许对起点和终点的速度进行控制。Hermite插值不仅仅考虑了...
这个压缩包包含的代码示例展示了如何在Java的图形用户界面(GUI)上绘制三种不同类型的曲线:Hermite曲线、Bezier曲线和B样条曲线。以下是对这些曲线的详细解释: 1. Hermite曲线: Hermite曲线是一种基于四个控制...
本实验基于MFC(Microsoft Foundation Classes)框架,利用C++编程语言实现了三种常见类型的参数曲线:Bezier曲线、B样条曲线以及Hermite曲线。下面将详细解释这三种曲线的原理和实现方法。 **Bezier曲线**: ...
在计算机图形学中,Bezier曲线是一种非常重要的数学工具,它被广泛用于图像绘制、游戏开发、CAD系统等。...无论是游戏中的角色动画,还是设计软件中的自由曲线绘制,Bezier曲线都是一个强大且灵活的工具。
在VC6.0 MFC下编写的源代码中,Bezier曲线的实现允许用户通过控制点轻松调整和绘制曲线。 B样条曲线(B-Spline Curve)是另一种常用的参数化曲线,它通过一组控制点和权系数来定义,具有更灵活的形状控制和更好的...
Hermite曲线则是基于导数信息的曲线,与Bezier曲线相比,它允许我们控制曲线的切线方向,而不只是端点位置。Hermite曲线的构建通常需要端点位置和两个端点的切线信息。这使得Hermite曲线能够更好地模拟物理现象,如...
基本图形绘制、图形变换、自由曲线绘制、图形裁剪或图形填充 二、二级子菜单基本图形绘制 1.直线绘制: 1)Bresenham绘制直线 2)DDA绘制直线 3)改进的Bresenham绘制直线 4)系统库函数绘制直线——直线线宽...
基本图形绘制、图形变换、自由曲线绘制、图形裁剪、图形填充 二、二级子菜单(基本图形绘制) 1.直线绘制: 1)Bresenham绘制直线 2)DDA绘制直线 3)改进的Bresenham绘制直线 4)系统库函数绘制直线——直线线宽、...
实验关键代码包括:Hermite 曲线绘制函数、Bezier 曲线绘制函数、B样条曲线绘制函数和矩阵相乘函数等。这些函数的实现细节见代码列表。 本实验让我们了解了 Hermite、Bezier、B样条三种曲线算法,并掌握了基于 Win...
多点插值的埃米尔特曲线、贝齐尔曲线及 B 样条曲线绘制。 通过鼠标输入型值点,根据用户输入的型值点,分别绘制 Hermite 曲线,三次 Bezier 曲线,四阶三次等距 B 样条曲线(可 通过菜单或工具条选择具体要绘制哪种...
本课程设计的重点是利用C++ MFC进行计算机图形学的程序设计,特别是关于Bezier曲线、B样条和Hermite曲线的实现。 Bezier曲线是计算机图形学中一种基本的参数曲线,由法国工程师Pierre Bezier于1962年提出。它通过一...
本实验报告的目的是实现自由曲线的生成算法,包括 Hermite 曲线、Bezier 曲线和 B 样条曲线等。自由曲线是一种数学函数,可以用来描述复杂的曲线形状。通过编写程序实现这些自由曲线,可以实现在计算机图形学中绘制...