朱金灿
假如我们采用矢量表达式来表示参数化的二次曲线,那么可以把抛物线的表达式写成如下的一般形式:
P(t)=A1+ A2t+ A3t2 (0=<t<=1)
该抛物线过P1, P2, P3三个点,并且:
1. 抛物线以P1点为始点。当参变量t=0时,曲线过P1点;
2. 抛物线以P3点为终点。当参变量t=0时,曲线过P3点;
3. 当参变量t=0.5时,曲线过P2点,且切矢量等于P3—P1。
t=0: P(0)= A1= P1
t=1: P(1)= A1 + A2+ A3=P3
t=0.5:P(0.5)= A1 + 0.5A2+0.25 A3=P2
通过解联立方程,得到三个参数A1 、 A2、 A3分别为:
A1 = P1
A2=4 P2—P3—3P1
A3=2P1+2P3—4P2
把求出的这三个系数的值,代入抛物线的表达式P(t)=A1+ A2t+ A3t2
得:P(t)=(2t—3t+1)P1 +(4t—4t2)P2+(4t2—t)P3 (0=<t<=1)
设有一离散型值点列Pi(i=1,2,……,n),每经过相邻三点作一段抛物线,由于有n个型值点,所以可以做n-2条抛物线段。
在这n—2条抛物线段中,第i条抛物线段为经过Pi, Pi+1, Pi+2三点,所以它的表达式应为:Si(ti)=(2t2i—3ti+1)Pi +(4 ti—4 t2i) Pi+1 +(2t2i—ti) Pi+2 (0=< ti <=1)
同理,第i+1条抛物线段为经过Pi+1, Pi+2, Pi+3三点,所以它的表达式应为:Si+1(ti+1)=(2t2i+1—3ti+1+1)Pi+1 +(4 ti+1—4 t2i+1) Pi+2 +(2t2i+1—ti+1) Pi+3 (0=< ti+1 <=1)
一般来说,每两段曲线之间的搭接区间,两条抛物线是不可能重合的。如下图所示:
显然,对于拟合曲线来说,整个型值点必须只能用一条光滑的曲线连接起来。为了做到这一点,必须找一种方法把Si和Si+1 这样的曲线段的共同区间结合起来。这种方法就是加权合成方法。
我们设共同区间的函数是Pi+1(t)=f (T ) Si(ti)+g ( T) Si+1(ti+1). 其中f (T ) 和 g ( T) 是权函数。在抛物样条曲线中我们取简单的一次函数为权函数,且具有互补性,设
f (T ) =1—T
g ( T) =T
这样Pi+1(t)= (1—T ) Si(ti)+ T Si+1(ti+1).因为 函数中有T、ti和ti+1三个参数,因此接下来我们的工作是统一参数。我们可以三个参变量统一形式为:
T=2t
ti=0.5+t
ti+1=t
这样Pi+1(t)= (—2t3+4t2—t)Pi +(12t3—410t2+1) Pi+1 +(—12t3+8t2+t) Pi+2 +(4t3—2t2) Pi+3 (0=< ti <=0.5)
从几何意义上说,函数Pi+1(t)表示的上图的点Pi+1,到Pi+2 之间的线段。但是我们应该看到这种方法从n个点中只能得到n—3段曲线。但是n个型值点应有n—1段曲线。一个直接的想法是添加两个辅助点。那么如何添加呢?
方法一:两个辅助点为P0和Pn+1, P0=P1,Pn+1= Pn ,这样画出的曲线为一条不闭合的自由曲线。
方法二:添加三个辅助点,P0、Pn+1和Pn+2,然后P0=Pn,Pn+1= P1, ,Pn+2= P2,这样画出的曲线为一条闭合的曲线。
下面介绍根据上面原理而设计的一个画抛物曲线的一个类:
class CParspl : public CObject
{
DECLARE_SERIAL(CParspl)
public:
CParspl(int nLineStyle,int nLineWidth, COLORREF crLineColor);
virtual ~CParspl();
void SetPoint(const CPoint &point); // 添加坐标点
void DrawFreeLine(CDC *pDC);// 画自由端抛物曲线
void DrawCloseLine(CDC *pDC); // 画封闭端抛物曲线
void Serialize(CArchive & ar);
protected:
CParspl();
/*public attributes*/
public:
int m_bIsFreeLine;
/*private attibutes*/
private:
CArray<CPoint,CPoint> ParsplPoint; // 定义插值点数组
COLORREF m_crLineColor; // 定义线色
int m_nLineStyle; // 定义线型
int m_nLineWidth; //定义线宽
};
const int Clip=10;
CParspl::CParspl() // 默认的构造函数
{
}
CParspl::~CParspl()
{
}
CParspl::CParspl(int nLineStyle,int nLineWidth, COLORREF crLineColor)
{
m_nLineStyle = nLineStyle;
m_nLineWidth = nLineWidth;
m_crLineColor = crLineColor;
ParsplPoint.Add(CPoint(0,0)); //初始化第一个点
m_bIsFreeLine = 1;
}
void CParspl::SetPoint(const CPoint &point)
{
ParsplPoint.Add(point);
}
void CParspl::DrawFreeLine(CDC *pDC)
{
if(ParsplPoint.GetSize() < 4) return;
CPen LinePen(m_nLineStyle,m_nLineWidth,m_crLineColor);
int i=0,j=0;
int n=0;
n=ParsplPoint.GetSize();
double t1,t2,t3,t,a,b,c,d,x,y;
ParsplPoint[0].x=ParsplPoint[1].x;
ParsplPoint[0].y=ParsplPoint[1].y;
CPoint pt=ParsplPoint.GetAt(n-1);
ParsplPoint.Add(pt);
t=<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue=".5" unitname="F" w:st="on">0.5f</chmetcnv>/Clip;
CPen *pLinePen=pDC->SelectObject(&LinePen);
pDC->MoveTo(ParsplPoint[1].x,ParsplPoint[1].y);
for (i=0;i<n-2;i++)
{
for(j=1;j<Clip;j++)
{
t1=j*t;
t2=t1*t1;
t3=t2*t1;
a=4.0*t2-t1-4.0*t3;
b=1.0-10.0*t2+12.0*t3;
c=t1+8.0*t2-12.0*t3;
d=4.0*t3-2.0*t2;
x=a*ParsplPoint[i].x+b*ParsplPoint[i+1].x+c*ParsplPoint[i+2].x+d*ParsplPoint[i+3].x;
y=a*ParsplPoint[i].y+b*ParsplPoint[i+1].y+c*ParsplPoint[i+2].y+d*ParsplPoint[i+3].y;
pDC->LineTo(int(x),int(y));
}
pDC->LineTo(ParsplPoint[i+2].x,ParsplPoint[i+2].y);
}
for(i=0;i<n;i++)
{
pt=ParsplPoint.GetAt(i);
pDC->Ellipse(pt.x-2,pt.y-2,pt.x+2,pt.y+2);
}
/* 将旧画笔选回设备环境*/
pDC->SelectObject(pLinePen);
/*删除辅助点*/ ParsplPoint.RemoveAt(ParsplPoint.GetUpperBound());
}
void CParspl::DrawCloseLine(CDC *pDC)
{
if(ParsplPoint.GetSize() < 4) return;
CPen LinePen(m_nLineStyle,m_nLineWidth,m_crLineColor);
int i=0,j=0;
int n=0;
n=ParsplPoint.GetSize();
double t1,t2,t3,t,a,b,c,d,x,y;
ParsplPoint[0].x=ParsplPoint[n-1].x;
ParsplPoint[0].y=ParsplPoint[n-1].y;
CPoint pt=ParsplPoint.GetAt(1);
ParsplPoint.Add(pt);
pt=ParsplPoint.GetAt(2);
ParsplPoint.Add(pt);
t=<chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue=".5" unitname="F" w:st="on">0.5f</chmetcnv>/Clip;
CPen *pLinePen=pDC->SelectObject(&LinePen);
pDC->MoveTo(ParsplPoint[1].x,ParsplPoint[1].y);
for (i=0;i<n-1;i++)
{
for(j=1;j<Clip;j++)
{
t1=j*t;
t2=t1*t1;
t3=t2*t1;
a=4.0*t2-t1-4.0*t3;
b=1.0-10.0*t2+12.0*t3;
c=t1+8.0*t2-12.0*t3;
d=4.0*t3-2.0*t2;
x=a*ParsplPoint[i].x+b*ParsplPoint[i+1].x+c*ParsplPoint[i+2].x+d*ParsplPoint[i+3].x;
y=a*ParsplPoint[i].y+b*ParsplPoint[i+1].y+c*ParsplPoint[i+2].y+d*ParsplPoint[i+3].y;
pDC->LineTo(int(x),int(y));
}
pDC->LineTo(ParsplPoint[i+2].x,ParsplPoint[i+2].y);
}
for(i=0;i<n;i++)
{
pt=ParsplPoint.GetAt(i);
pDC->Ellipse(pt.x-2,pt.y-2,pt.x+2,pt.y+2);
}
/*将旧画笔选回设备环境*/
pDC->SelectObject(pLinePen);
/*删除最后两个辅助点*/
ParsplPoint.RemoveAt(ParsplPoint.GetUpperBound());
ParsplPoint.RemoveAt(ParsplPoint.GetUpperBound());
}
程序效果图:
自由端曲线:
封闭端曲线:
分享到:
相关推荐
如果所画曲线不需要首尾相连,则单击右键即可; 如果要求所画的曲线首尾相连,则先按下Ctrl键(为了与鼠标右键同时按下),在单击鼠标右键; 重画曲线:双击左键即可; 退出程序:双击右键即可;
环境:vs2008 语言:C# Spline.cs是封装的实体类 CSGLControl.cs继承OpenGLControl 在CSGLControl下调用Spline实体的Draw方法就行了
分段二次抛物样条插值法,张永利,,希尔伯特-黄变换(HHT)是一种新型的信号处理方法,由经验模态分解和希尔伯特变换两部分所组成,其中在经验模态分解中使用了三次样条
计算机图形学 抛物及三次样条曲线.ppt
给出了一种带形状参数的三次三角Hermite插值样条曲线,具有标准三次Hermite插值样条曲线完全相同的性质。给定插值条件时,样条曲线的形状可通过改变形状参数的取值进行调控。在适当条件下,该样条曲线对应的Ferguson...
将形状参数与三角函数进行有机结合,构造了一组含参数的三角基,由这组基定义了带形状参数的三角样条曲线,其每一段由相继的5个控制顶点生成。新曲线在继承B样条曲线主要优点的同时,既具有形状可调性,又能精确表示...
1、 绘制类: 箭头、示坡线、锥坡线、剖断线、垂线、切线、等高线加密、Hatch轮廓线等; 2、 标注类: 各类引线标注(圆形、坐标、断面、...14、信息类: 实体DXF码列表、多段线顶点及点坐标列表、面积及曲线长度查询等;
142 抛物样条曲线 143 Mandelbrot分形图案 144 绘制布朗运动曲线 145 艺术清屏 146 矩形区域的颜色填充 147 VGA256色模式编程 148 绘制蓝天图案 149 屏幕检测程序 150 运动的小车动画 151 动态显示位图 152...
研究了区间值模糊软集的代数性质。给出了相关算子的一些性质,证明了De Morgan对偶律是成立的;建立了区间值模糊软集的两种格结构;得到这两种格均是分配格。
基于三点的抛物线插值函数。与Matlab中spline()在三个数据点时的结果一致。注意,大于三点的样条插值函数需要求解线性方程组,运算复杂,实时性较低。可参考Lapack及数值计算书籍
基于不在同一条直线上三点的抛物线插值函数。与Matlab中spline()在三个数据点时的结果一致。注意,大于三点的样条插值函数需要求解线性方程组,运算复杂,实时性较低。可参考Lapack及数值计算书籍
且是从给定的一组实验数据出发,寻求已知函数的一个逼近函数y=ρ(x),使得逼近函数从总体上来说与已知函数的偏差按某种方法度量能达到最小而又不一定过全部的点(xi,yi),即是最小二乘曲线拟合。本软件就是针对这些...
兰萨克兰萨克曲线拟合这是使用RANSAC查找抛物线的示例。 这是使用RANSAC算法获取曲率的示例来源参考页面为并将参考页面上介绍的MATLAB代码转换为C ++代码。 我参考了 ,并将Matlab代码转换为C ++代码OpenCV用于矩阵...
本书共十章,主要包括计算机绘图基本知识、平面图形设计、图形变换、物体视图及表面展开、立体图的自动绘制、三维立体消隐、实测曲线绘制、曲线拟合与设计、曲面设计和VBA与三维实体造型技术等方面内容。可作为工科...
测试QT的测试抛物样条曲线、贝塞尔曲线,并进行对比分析
基于最小二乘法道路平面曲线拟合,高盼,,目前我们用于公路平面设计中曲线光滑的方法主要是三次多项式插值法,抛物线加权平均法,张力样条函数插值法,但这些方法计算量大
基于VC的三种端点条件的插值B样条曲线绘制,包括夹持端点,自由端点,抛物线端点,线性方程组的解法采用了追赶法。
本文首先将四阶抛物型方程转化为一个二阶的偏微分方程组,然后对时间项采用子域精细积分的方法、空间项采用三次样条基本公式进行离散,得到了一个含参数α>O(α h)的无条件稳定的差分格式,所得到的差分方程为五点...
对三次样条插值函数的m文件,下载可直接可用,用于matlab编程设计和课程作用 对三次样条插值函数的m文件,下载可直接可用,用于matlab编程设计和课程作用
提出了在一个空间维度上求解一般线性抛物型偏微分方程(PDE)的新方法。 这些方法结合了用于空间离散化的二次样条搭配和用于时间离散化的经典有限差分(例如Crank-Nicolson)。 最有效方法的主要计算要求是在每个...