OPEN CASCADE BSpline Curve Interpolation
OPEN CASCADE BSpline Curve Interpolation
Abstract. Global curve interpolation to point data is a way to construct curves. The paper focus on the interpolate algorithm in OPEN CASCADE, and give a simple example to demonstrate the usage of the GeomAPI_Interpolate class.
Key Words. Interpolate, NURBS, BSpline, OPEN CASCADE
1.Introduction
曲线曲面拟合Curve and Surface Fitting的方式可以分为两类:插值interpolation和逼近approximation。采用插值的方式时,所创建的曲线或曲面必须精确地满足所给的数据条件,例如曲线通过所给的插值点。采用逼近的方式时,创建的曲线或曲面不必精确地满足所给的数据条件,只要在一定的误差范围内接近即可,如下图所示:
![]()
Figure 1.1 A curve interpolating five points and end derivatives(The NURBS Book)
![]()
Figure 1.2 A curve approximating points(The NURBS Book)
本文先简要介绍B样条插值的原理,再结合OPEN CASCADE源码说明如何对给定点插值B样条曲线及OPEN CASCADE中插值曲线的一些注意事项。
2.Global Interpolation
假设给定一组数据点{Qk},k=0,1,…n,我们想要用一条p次非有理B样条曲线插值于这些点。如果我们为每个点Qk指定了一个参数值uk,并且选定了一个合适的节点矢量U,我们就可以建立一个系数矩阵为(n+1)x(n+1)的线性方程组:
![]()
n+1个控制点Pi是未知量。剩下的问题是如何确定Qk对应的参数值uk及节点矢量U,这将影响到曲线的形状和参数化。常见的选取uk的方法有均匀参数化法、弦长参数化法和向心参数化法。
2.1 Equally Spaced 均匀参数法
假设参数限定在[0,1]范围内,那么
![]()
当参数范围为[a,b]时,
![]()
均匀参数化法是最简单的构造参数的方法,但是不推荐采用这种方法,因为当数据点分布步均匀时,会产生很奇怪的形状,如打圈自交。
![]()
Figure 2.1 B-Spline curve interpolation with the uniformly spaced method[1]
2.2 Chord Length 弦长参数法
令d为总弦长,且把参数范围限定在[0,1]之间,则:
![]()
这是最常用的方法,并且一般用它就足够了,考虑到弦长参数化接近曲线的均匀参数化,在这种意义下,它给出了曲线的一个“好”的参数化。
2.3 Centripetal Method 向心参数法
![]()
这是一个更新的方法,当数据点急转弯变化时,这个方法能得到比弦长参数化更好的结果。
3.BSpline Interpolation in OPEN CASCADE
OPEN CASCADE对曲线的插值是通过GeomAPI包中的GeomAPI_Interpolate实现的。由其代码注释可知,这个类的功能是可以对一系列点进行插值得到C2连续的B样条曲线,当对插值点处的切矢不作要求时。对点直接插值的构造函数为:
GeomAPI_Interpolate (const Handle< TColgp_HArray1OfPnt > &Points, const Standard_Boolean PeriodicFlag, const Standard_Real Tolerance)
其中参数Points为插值点,PeriodicFlag为是否周期曲线,Tolerance是对插值点进行检查用的容差。Tolerance容易产生误解,根据插值曲线的定义,插值曲线是要求通过插值点的,所以不存在插值得到的曲线和插值点之间的容差。
经过查看OPEN CASCADE中插值曲线的源码,可以得出对曲线进行插值的步骤如下:
v 检查是否有重复的插值点CheckPoints;
v 生成参数BuildParameters;
v 使用BSplCLib::Interpolate()进行插值;
v 根据参数及次数生成系数矩阵,再结合插值点,对系数矩阵和插值点组成的方程组进行求解。
检查插值点代码如下:
static Standard_Boolean CheckPoints(const TColgp_Array1OfPnt& PointArray,
const Standard_Real Tolerance)
{
Standard_Integer ii ;
Standard_Real tolerance_squared = Tolerance * Tolerance,
distance_squared ;
Standard_Boolean result = Standard_True ;
for (ii = PointArray.Lower() ; result && ii < PointArray.Upper() ; ii++) {
distance_squared =
PointArray.Value(ii).SquareDistance(PointArray.Value(ii+)) ;
result = (distance_squared >= tolerance_squared) ;
}
return result ; }
由上述代码可知,Tolerance主要是用于检查插值点是否在容差范围内有重合现象。生成参数代码如下:
static void BuildParameters(const Standard_Boolean PeriodicFlag,
const TColgp_Array1OfPnt& PointsArray,
Handle(TColStd_HArray1OfReal)& ParametersPtr)
{
Standard_Integer ii,
index ;
Standard_Real distance ;
Standard_Integer
num_parameters = PointsArray.Length() ;
if (PeriodicFlag) {
num_parameters += ;
}
ParametersPtr =
new TColStd_HArray1OfReal(,
num_parameters) ;
ParametersPtr->SetValue(,0.0e0) ;
index = ;
for (ii = PointsArray.Lower() ; ii < PointsArray.Upper() ; ii++) {
distance =
PointsArray.Value(ii).Distance(PointsArray.Value(ii+)) ;
ParametersPtr->SetValue(index,
ParametersPtr->Value(ii) + distance) ;
index += ;
}
if (PeriodicFlag) {
distance =
PointsArray.Value(PointsArray.Upper()).
Distance(PointsArray.Value(PointsArray.Lower())) ;
ParametersPtr->SetValue(index,
ParametersPtr->Value(ii) + distance) ;
}
}
由上述代码可知,OPEN CASCADE插值生成参数的方法如下:
![]()
不是上述三种常用方法的之一,和弦长参数化法类似,但是没有去除以总弦长。生成节点矢量之前为了得到曲线的次数,做了如下处理:
if (num_poles == && !myTangentRequest) {
degree = ;
}
else if (num_poles == && !myTangentRequest) {
degree = ;
num_distinct_knots = ;
}
else {
degree = ;
num_poles += ;
if (myTangentRequest)
for (ii = myTangentFlags->Lower() + ;
ii < myTangentFlags->Upper() ; ii++) {
if (myTangentFlags->Value(ii)) {
num_poles += ;
}
}
}
由上述代码可知,插值要求至少有两个插值点。当只有两个插值点时,插值曲线次数为1,即为直线;当有三个插值点且没有切矢的要求时,插值曲线次数为2次;当插值点数多于3个时,插值曲线次数为3。即对于多于三个点进行插值时,最高只能得到3次曲线,也即C2连续的曲线。进行B样条插值的代码如下:
void BSplCLib::Interpolate(const Standard_Integer Degree,
const TColStd_Array1OfReal& FlatKnots,
const TColStd_Array1OfReal& Parameters,
const TColStd_Array1OfInteger& ContactOrderArray,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Integer& InversionProblem)
{
Standard_Integer ErrorCode,
UpperBandWidth,
LowerBandWidth ;
// Standard_Real *PolesArray = &Poles ;
math_Matrix InterpolationMatrix(, Parameters.Length(),
, * Degree + ) ;
ErrorCode =
BSplCLib::BuildBSpMatrix(Parameters,
ContactOrderArray,
FlatKnots,
Degree,
InterpolationMatrix,
UpperBandWidth,
LowerBandWidth) ;
if(ErrorCode)
Standard_OutOfRange::Raise("BSplCLib::Interpolate"); ErrorCode =
BSplCLib::FactorBandedMatrix(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
InversionProblem) ;
if(ErrorCode)
Standard_OutOfRange::Raise("BSplCLib::Interpolate"); ErrorCode =
BSplCLib::SolveBandedSystem(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
ArrayDimension,
Poles) ;
if(ErrorCode)
Standard_OutOfRange::Raise("BSplCLib::Interpolate");
}
先是根据参数及插值曲线次数生成系数矩阵,再对系数矩阵和插值点构成的方程组进行求解,计算出B样条曲线的控制顶点Poles。有了节点矢量,次数及控制顶点,B样条就确定下来了:
myCurve =
new Geom_BSplineCurve(poles,
myParameters->Array1(),
mults,
degree) ;
myIsDone = Standard_True ;
OPEN CASCADE提供的插值接口使用还是很简单的,如对已经知点进行插值,其用法如下:
int main(int argc, char* argv[])
{
Handle_TColgp_HArray1OfPnt aPoints = new TColgp_HArray1OfPnt aPoints(, );
Handle_Geom_BSplineCurve aBSplineCurve; aPoints.SetValue(, gp_Pnt(0.0, 0.0, 0.0));
aPoints.SetValue(, gp_Pnt(1.0, 1.0, 0.0));
aPoints.SetValue(, gp_Pnt(2.0, 6.0, 3.0)); GeomAPI_Interpolate aInterpolater(aPoints, Standard_False, Precision::Approximation()); if (aInterpolater.IsDone())
{
aBSplineCurve = aInterpolater.Curve(); GeomTools::Dump(aBSplineCurve, std::cout);
}
}
4.Conclusion
综上所述,对给定点进行B样条插值时,需要考虑参数值及节点矢量的选择。参数值和节点矢量确定后,剩下就是利用B样条基函数对给定点的参数计算得到的系数组成的线性方程进行求解。
在使用OPEN CASCADE的曲线插值类GeomAPI_Interpolate时,需要注间容差Tolerance是用来对插值点进行检查的,且插值得到的曲线最高只能是三次曲线。
5.Acknowledgments
首先,感谢cnblog提供了一个表现自己的舞台http://www.cppblog.com/eryar/,能在网上和世界连通,知道不是一个人在战斗。
其次,感谢OPEN CASCADE的开源分享,才得以学到几何造型相关的知识,比起直接啃国内教材来,学习效率不可同日而语。正如“Talk is cheap, show me the code”所说,将代码和书本结合起来学习时,收获更大。
最后,感谢国内外友人对我的肯定和鼓励,他们自强不息,激情创业的精神总是让人兴奋。
生活的理想就是为了理想的生活The ideal of life is to live for ideals!人生充满了起起落落,关键在于在顶端时尽情享受,在低谷时不失勇气。
6.References
1. Hongxin Zhang, Jieqing Feng. B-Spline Interpolation and Approximation. Zhejiang University. 2006-12-18. http://www.cad.zju.edu.cn/home/zhx/GM/009/00-bsia.pdf
2. Les Piegl, Wayne Tiller. The NURBS Book. Springer-Verlag. 1995
3. 赵罡, 穆国旺, 王拉柱译. 非均匀有理B样条. 清华大学出版社. 1995
4. 易大义, 陈道琦. 数值分析引论. 浙江大学出版社. 1998
PDF Version: OPEN CASCADE BSpline Curve Interpolation
OPEN CASCADE BSpline Curve Interpolation的更多相关文章
- Convert BSpline Curve to Arc Spline in OpenCASCADE
Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCA ...
- OpenCascade B-Spline Basis Function
OpenCascade B-Spline Basis Function eryar@163.com Abstract. B-splines are quite a bit more flexible ...
- Open CASCADE Technology: IGES Support
2015/6/4 Open CASCADE Technology: IGES Support http://www.opencascade.org/doc/occt6.7.0/overview/ht ...
- OpenCASCADE Conic to BSpline Curves-Circle
OpenCASCADE Conic to BSpline Curves-Circle eryar@163.com Abstract. The conic sections and circles pl ...
- OpenCASCADE Conic to BSpline Curves-Hyperbola
OpenCASCADE Conic to BSpline Curves-Hyperbola eryar@163.com Abstract. Rational Bezier Curve can repr ...
- OpenCASCADE Conic to BSpline Curves-Parabola
OpenCASCADE Conic to BSpline Curves-Parabola eryar@163.com Abstract. Rational Bezier Curve can repre ...
- Geometry Curve of OpenCascade BRep
Geometry Curve of OpenCascade BRep eryar@163.com 摘要Abstract:几何曲线是参数表示的曲线 ,在边界表示中其数据存在于BRep_TEdge中,BR ...
- B-spline Curves 学习之B样条曲线的导数(8)
Derivatives of a B-spline Curve 本博客转自前人的博客的翻译版本,前几章节是原来博主的翻译内容,但是后续章节博主不在提供翻译,后续章节我在完成相关的翻译学习. (原来博客 ...
- Render OpenCascade Geometry Curves in OpenSceneGraph
在OpenSceneGraph中绘制OpenCascade的曲线 Render OpenCascade Geometry Curves in OpenSceneGraph eryar@163.com ...
随机推荐
- cassandra写数据CommitLog
cassandra 两种方式: Cassandra-ArchitectureCommitLog Cassandra持久化-Durability 一种是配置commitlog_sync为periodic ...
- linux菜鸟日记(3)
Centos7利用shell编辑一串 一键完成一些基础配置的代码: 在这串shell代码中我实现了 IP地址的配置.光盘的挂载.本地yum源的搭建.一些服务的安装例如 httpd. php. ntp ...
- PHP用户注册与登录完整代码【4】
login.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:// ...
- PHP用户注册与登录【1】
需求分析 主要功能分为 用户注册.用户登录.用户退出.用户中心 四个部分. 用户注册 用户注册主要功能有: 注册信息表单填写界面 javascript 脚本初步检测用户输入的注册信息. 注册处理模块检 ...
- PyCharm 代码完成/代码提示
因为python是动态语言,所以在有些情况ide会无法有效代码提示,见下: import sqlite3 conn = sqlite3.connect('d:/xxx.db') conn. #这里按 ...
- PL/SQL Developer如何连接64位的Oracle图解
在64位Win7系统上安装64位的Oracle数据库,但是没有对应的64位PL/SQL Developer,此时就不能使用PL/SQL Developer来进行直接连接的,所以要想实现连接还得需要其他 ...
- SQL Server 里的递归查询
http://www.360doc.com/content/13/0607/11/8463843_291221684.shtml
- Html5+Css3制作下拉菜单的三种方式
一.渐变式改变ol的高度 1.外部为ul标签,在每个li里嵌套一个ol列表2.设置外部li左浮动,内部ol标签绝对定位,外部li标签相对定位3.设置ol的高为0,溢出隐藏4.外部li标签:hover ...
- python中的参数问题
python中的有默认参数和可变参数之分 默认参数arg 可变参数args, kargs 默认参数arg就是调用指定参数 可变参数*arg调用时传入的的参数会被python自动包装为列表 可变参数ka ...
- NFSv4的引用,迁移和备份(用户手册 v0.2)
RFC3530 定义了NFS文件系统迁移和引用的管理机制.文件系统定位功能通过fs_location属性向客户端提供文件系统的位置信息.fs_location属 性是一个包含有位置信息的列表,位置信息 ...